am 4afe275: AI 147780: add summary of "future-proofing your apps" and li

Merge commit '4afe275c984fc943d11b26857aa81c501f5b294f' into donut

* commit '4afe275c984fc943d11b26857aa81c501f5b294f':
  AI 147780: add summary of "future-proofing your apps" and links
diff --git a/Android.mk b/Android.mk
index e373859..de5f5f8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -43,7 +43,7 @@
 
 ## READ ME: ########################################################
 ##
-## When updading this list of aidl files, consider if that aidl is
+## When updating this list of aidl files, consider if that aidl is
 ## part of the SDK API.  If it is, also add it to the list below that
 ## is preprocessed and distributed with the SDK.  This list should
 ## not contain any aidl files for parcelables, but the one below should
@@ -96,6 +96,8 @@
 	core/java/android/view/IWindow.aidl \
 	core/java/android/view/IWindowManager.aidl \
 	core/java/android/view/IWindowSession.aidl \
+	core/java/android/speech/IRecognitionListener.aidl \
+	core/java/android/speech/IRecognitionService.aidl \
 	core/java/com/android/internal/app/IBatteryStats.aidl \
 	core/java/com/android/internal/app/IUsageStats.aidl \
 	core/java/com/android/internal/appwidget/IAppWidgetService.aidl \
@@ -109,9 +111,12 @@
 	core/java/com/android/internal/view/IInputMethodManager.aidl \
 	core/java/com/android/internal/view/IInputMethodSession.aidl \
 	im/java/android/im/IImPlugin.aidl \
+	location/java/android/location/IGeocodeProvider.aidl \
 	location/java/android/location/IGpsStatusListener.aidl \
+	location/java/android/location/ILocationCollector.aidl \
 	location/java/android/location/ILocationListener.aidl \
 	location/java/android/location/ILocationManager.aidl \
+	location/java/android/location/ILocationProvider.aidl \
 	media/java/android/media/IAudioService.aidl \
 	media/java/android/media/IMediaScannerListener.aidl \
 	media/java/android/media/IMediaScannerService.aidl \
@@ -119,8 +124,8 @@
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
-	telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl \
-	telephony/java/com/android/internal/telephony/gsm/ISms.aidl \
+	telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl \
+	telephony/java/com/android/internal/telephony/ISms.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
 	telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl
 
@@ -439,3 +444,5 @@
 ifeq (,$(ONE_SHOT_MAKEFILE))
 include $(call first-makefiles-under,$(LOCAL_PATH))
 endif
+
+
diff --git a/api/current.xml b/api/current.xml
index d646f4f..1bf1d5a9 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -848,6 +848,17 @@
  visibility="public"
 >
 </field>
+<field name="SDCARD_WRITE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.SDCARD_WRITE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SEND_SMS"
  type="java.lang.String"
  transient="false"
@@ -1283,6 +1294,17 @@
  visibility="public"
 >
 </field>
+<field name="STORAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission-group.STORAGE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SYSTEM_TOOLS"
  type="java.lang.String"
  transient="false"
@@ -1350,6 +1372,39 @@
  visibility="public"
 >
 </field>
+<field name="anticipate_interpolator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432583"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="anticipate_overshoot_interpolator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="bounce_interpolator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432586"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="decelerate_interpolator"
  type="int"
  transient="false"
@@ -1383,6 +1438,17 @@
  visibility="public"
 >
 </field>
+<field name="overshoot_interpolator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432584"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="slide_in_left"
  type="int"
  transient="false"
@@ -2550,6 +2616,17 @@
  visibility="public"
 >
 </field>
+<field name="density"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843372"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dependency"
  type="int"
  transient="false"
@@ -3133,6 +3210,17 @@
  visibility="public"
 >
 </field>
+<field name="extraTension"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843371"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="factor"
  type="int"
  transient="false"
@@ -7137,6 +7225,17 @@
  visibility="public"
 >
 </field>
+<field name="tension"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843370"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="text"
  type="int"
  transient="false"
@@ -10186,6 +10285,28 @@
  visibility="public"
 >
 </field>
+<field name="stat_sys_vp_phone_call"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17302061"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="stat_sys_vp_phone_call_on_hold"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17302062"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="stat_sys_warning"
  type="int"
  transient="false"
@@ -28258,6 +28379,28 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_POWER_CONNECTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.ACTION_POWER_CONNECTED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POWER_DISCONNECTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.ACTION_POWER_DISCONNECTED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_PROVIDER_CHANGED"
  type="java.lang.String"
  transient="false"
@@ -31519,6 +31662,17 @@
  visibility="public"
 >
 </field>
+<field name="supportsDensities"
+ type="int[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="taskAffinity"
  type="java.lang.String"
  transient="false"
@@ -33509,6 +33663,17 @@
  visibility="public"
 >
 </field>
+<field name="GET_SUPPORTS_DENSITIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32768"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="GET_UNINSTALLED_PACKAGES"
  type="int"
  transient="false"
@@ -57915,7 +58080,7 @@
  type="float"
  transient="false"
  volatile="false"
- value="0.001f"
+ value="0.0010f"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -73127,6 +73292,10412 @@
 >
 </field>
 </class>
+<class name="GLES10"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GLES10"
+ type="android.opengl.GLES10"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="glActiveTexture"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texture" type="int">
+</parameter>
+</method>
+<method name="glAlphaFunc"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="func" type="int">
+</parameter>
+<parameter name="ref" type="float">
+</parameter>
+</method>
+<method name="glAlphaFuncx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="func" type="int">
+</parameter>
+<parameter name="ref" type="int">
+</parameter>
+</method>
+<method name="glBindTexture"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="texture" type="int">
+</parameter>
+</method>
+<method name="glBlendFunc"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sfactor" type="int">
+</parameter>
+<parameter name="dfactor" type="int">
+</parameter>
+</method>
+<method name="glClear"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mask" type="int">
+</parameter>
+</method>
+<method name="glClearColor"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="float">
+</parameter>
+<parameter name="green" type="float">
+</parameter>
+<parameter name="blue" type="float">
+</parameter>
+<parameter name="alpha" type="float">
+</parameter>
+</method>
+<method name="glClearColorx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="int">
+</parameter>
+<parameter name="green" type="int">
+</parameter>
+<parameter name="blue" type="int">
+</parameter>
+<parameter name="alpha" type="int">
+</parameter>
+</method>
+<method name="glClearDepthf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="depth" type="float">
+</parameter>
+</method>
+<method name="glClearDepthx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="depth" type="int">
+</parameter>
+</method>
+<method name="glClearStencil"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="int">
+</parameter>
+</method>
+<method name="glClientActiveTexture"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texture" type="int">
+</parameter>
+</method>
+<method name="glColor4f"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="float">
+</parameter>
+<parameter name="green" type="float">
+</parameter>
+<parameter name="blue" type="float">
+</parameter>
+<parameter name="alpha" type="float">
+</parameter>
+</method>
+<method name="glColor4x"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="int">
+</parameter>
+<parameter name="green" type="int">
+</parameter>
+<parameter name="blue" type="int">
+</parameter>
+<parameter name="alpha" type="int">
+</parameter>
+</method>
+<method name="glColorMask"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="boolean">
+</parameter>
+<parameter name="green" type="boolean">
+</parameter>
+<parameter name="blue" type="boolean">
+</parameter>
+<parameter name="alpha" type="boolean">
+</parameter>
+</method>
+<method name="glColorPointer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="pointer" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glCompressedTexImage2D"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+<parameter name="internalformat" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="border" type="int">
+</parameter>
+<parameter name="imageSize" type="int">
+</parameter>
+<parameter name="data" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glCompressedTexSubImage2D"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+<parameter name="xoffset" type="int">
+</parameter>
+<parameter name="yoffset" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="format" type="int">
+</parameter>
+<parameter name="imageSize" type="int">
+</parameter>
+<parameter name="data" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glCopyTexImage2D"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+<parameter name="internalformat" type="int">
+</parameter>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="border" type="int">
+</parameter>
+</method>
+<method name="glCopyTexSubImage2D"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+<parameter name="xoffset" type="int">
+</parameter>
+<parameter name="yoffset" type="int">
+</parameter>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<method name="glCullFace"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="glDeleteTextures"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="textures" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDeleteTextures"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="textures" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glDepthFunc"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="func" type="int">
+</parameter>
+</method>
+<method name="glDepthMask"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="flag" type="boolean">
+</parameter>
+</method>
+<method name="glDepthRangef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="zNear" type="float">
+</parameter>
+<parameter name="zFar" type="float">
+</parameter>
+</method>
+<method name="glDepthRangex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="zNear" type="int">
+</parameter>
+<parameter name="zFar" type="int">
+</parameter>
+</method>
+<method name="glDisable"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cap" type="int">
+</parameter>
+</method>
+<method name="glDisableClientState"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="array" type="int">
+</parameter>
+</method>
+<method name="glDrawArrays"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+<parameter name="first" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+</method>
+<method name="glDrawElements"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="indices" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glEnable"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cap" type="int">
+</parameter>
+</method>
+<method name="glEnableClientState"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="array" type="int">
+</parameter>
+</method>
+<method name="glFinish"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="glFlush"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="glFogf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glFogfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glFogfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glFogx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glFogxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glFogxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glFrontFace"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="glFrustumf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="float">
+</parameter>
+<parameter name="right" type="float">
+</parameter>
+<parameter name="bottom" type="float">
+</parameter>
+<parameter name="top" type="float">
+</parameter>
+<parameter name="zNear" type="float">
+</parameter>
+<parameter name="zFar" type="float">
+</parameter>
+</method>
+<method name="glFrustumx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="int">
+</parameter>
+<parameter name="right" type="int">
+</parameter>
+<parameter name="bottom" type="int">
+</parameter>
+<parameter name="top" type="int">
+</parameter>
+<parameter name="zNear" type="int">
+</parameter>
+<parameter name="zFar" type="int">
+</parameter>
+</method>
+<method name="glGenTextures"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="textures" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGenTextures"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="textures" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetError"
+ return="int"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="glGetIntegerv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetIntegerv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetString"
+ return="java.lang.String"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="int">
+</parameter>
+</method>
+<method name="glHint"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="glLightModelf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glLightModelfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLightModelfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glLightModelx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glLightModelxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLightModelxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glLightf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glLightfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLightfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glLightx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glLightxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLightxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glLineWidth"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="float">
+</parameter>
+</method>
+<method name="glLineWidthx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+</method>
+<method name="glLoadIdentity"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="glLoadMatrixf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLoadMatrixf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glLoadMatrixx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLoadMatrixx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glLogicOp"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="opcode" type="int">
+</parameter>
+</method>
+<method name="glMaterialf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glMaterialfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glMaterialfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glMaterialx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glMaterialxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glMaterialxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glMatrixMode"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="glMultMatrixf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glMultMatrixf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glMultMatrixx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glMultMatrixx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glMultiTexCoord4f"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="s" type="float">
+</parameter>
+<parameter name="t" type="float">
+</parameter>
+<parameter name="r" type="float">
+</parameter>
+<parameter name="q" type="float">
+</parameter>
+</method>
+<method name="glMultiTexCoord4x"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="s" type="int">
+</parameter>
+<parameter name="t" type="int">
+</parameter>
+<parameter name="r" type="int">
+</parameter>
+<parameter name="q" type="int">
+</parameter>
+</method>
+<method name="glNormal3f"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nx" type="float">
+</parameter>
+<parameter name="ny" type="float">
+</parameter>
+<parameter name="nz" type="float">
+</parameter>
+</method>
+<method name="glNormal3x"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nx" type="int">
+</parameter>
+<parameter name="ny" type="int">
+</parameter>
+<parameter name="nz" type="int">
+</parameter>
+</method>
+<method name="glNormalPointer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="pointer" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glOrthof"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="float">
+</parameter>
+<parameter name="right" type="float">
+</parameter>
+<parameter name="bottom" type="float">
+</parameter>
+<parameter name="top" type="float">
+</parameter>
+<parameter name="zNear" type="float">
+</parameter>
+<parameter name="zFar" type="float">
+</parameter>
+</method>
+<method name="glOrthox"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="int">
+</parameter>
+<parameter name="right" type="int">
+</parameter>
+<parameter name="bottom" type="int">
+</parameter>
+<parameter name="top" type="int">
+</parameter>
+<parameter name="zNear" type="int">
+</parameter>
+<parameter name="zFar" type="int">
+</parameter>
+</method>
+<method name="glPixelStorei"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glPointSize"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="float">
+</parameter>
+</method>
+<method name="glPointSizex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+</method>
+<method name="glPolygonOffset"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factor" type="float">
+</parameter>
+<parameter name="units" type="float">
+</parameter>
+</method>
+<method name="glPolygonOffsetx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factor" type="int">
+</parameter>
+<parameter name="units" type="int">
+</parameter>
+</method>
+<method name="glPopMatrix"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="glPushMatrix"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="glReadPixels"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="format" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="pixels" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glRotatef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="angle" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="glRotatex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="angle" type="int">
+</parameter>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="glSampleCoverage"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="float">
+</parameter>
+<parameter name="invert" type="boolean">
+</parameter>
+</method>
+<method name="glSampleCoveragex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+<parameter name="invert" type="boolean">
+</parameter>
+</method>
+<method name="glScalef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="glScalex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="glScissor"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<method name="glShadeModel"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="glStencilFunc"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="func" type="int">
+</parameter>
+<parameter name="ref" type="int">
+</parameter>
+<parameter name="mask" type="int">
+</parameter>
+</method>
+<method name="glStencilMask"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mask" type="int">
+</parameter>
+</method>
+<method name="glStencilOp"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fail" type="int">
+</parameter>
+<parameter name="zfail" type="int">
+</parameter>
+<parameter name="zpass" type="int">
+</parameter>
+</method>
+<method name="glTexCoordPointer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="pointer" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glTexEnvf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glTexEnvfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexEnvfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glTexEnvx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexEnvxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexEnvxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glTexImage2D"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+<parameter name="internalformat" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="border" type="int">
+</parameter>
+<parameter name="format" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="pixels" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glTexParameterf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glTexParameterx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexSubImage2D"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+<parameter name="xoffset" type="int">
+</parameter>
+<parameter name="yoffset" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="format" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="pixels" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glTranslatef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="glTranslatex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="glVertexPointer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="pointer" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glViewport"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<field name="GL_ADD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="260"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALIASED_LINE_WIDTH_RANGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33902"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALIASED_POINT_SIZE_RANGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33901"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6406"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALPHA_BITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3413"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALPHA_TEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3008"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALWAYS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="519"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_AMBIENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4608"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_AMBIENT_AND_DIFFUSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5634"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_AND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5377"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_AND_INVERTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5380"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_AND_REVERSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5378"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1029"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3042"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLUE_BITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3412"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BYTE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5120"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CCW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2305"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLAMP_TO_EDGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33071"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLEAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5376"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_ARRAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32886"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_BUFFER_BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_LOGIC_OP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3058"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_MATERIAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2903"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COMPRESSED_TEXTURE_FORMATS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34467"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CONSTANT_ATTENUATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4615"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COPY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5379"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COPY_INVERTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5388"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CULL_FACE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2884"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2304"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DECAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8449"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DECR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7683"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_BITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3414"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_BUFFER_BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_TEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2929"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DIFFUSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4609"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DITHER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DONT_CARE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4352"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DST_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="772"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DST_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="774"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_EMISSION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5632"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_EQUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="514"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_EQUIV"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5385"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_EXP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2048"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_EXP2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2049"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_EXTENSIONS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7939"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FALSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FASTEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4353"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FIXED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5132"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FLAT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7424"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FLOAT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5126"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FOG"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2912"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FOG_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2918"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FOG_DENSITY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2914"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FOG_END"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2916"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FOG_HINT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3156"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FOG_MODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2917"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FOG_START"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2915"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRONT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1028"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRONT_AND_BACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1032"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_GEQUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="518"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_GREATER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="516"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_GREEN_BITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3411"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35739"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_IMPLEMENTATION_COLOR_READ_TYPE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35738"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INCR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7682"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INVALID_ENUM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1280"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INVALID_OPERATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1282"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INVALID_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1281"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INVERT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5386"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_KEEP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7680"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LEQUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="515"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="513"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT0"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16385"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16386"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16387"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16388"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16389"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16390"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16391"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2896"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT_MODEL_AMBIENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2899"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LIGHT_MODEL_TWO_SIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2898"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINEAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9729"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINEAR_ATTENUATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4616"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINEAR_MIPMAP_LINEAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9987"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINEAR_MIPMAP_NEAREST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9985"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINE_LOOP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINE_SMOOTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2848"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINE_SMOOTH_HINT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3154"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINE_STRIP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LUMINANCE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6409"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LUMINANCE_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6410"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_ELEMENTS_INDICES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_ELEMENTS_VERTICES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_LIGHTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3377"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_MODELVIEW_STACK_DEPTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3382"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_PROJECTION_STACK_DEPTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_TEXTURE_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3379"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_TEXTURE_STACK_DEPTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3385"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_TEXTURE_UNITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34018"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_VIEWPORT_DIMS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3386"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MODELVIEW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5888"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MODULATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8448"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MULTISAMPLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32925"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NAND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5390"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NEAREST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9728"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NEAREST_MIPMAP_LINEAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9986"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NEAREST_MIPMAP_NEAREST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9984"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NEVER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="512"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NICEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4354"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NOOP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5381"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NORMALIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2977"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NORMAL_ARRAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32885"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NOTEQUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="517"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NO_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NUM_COMPRESSED_TEXTURE_FORMATS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34466"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ONE_MINUS_DST_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="773"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ONE_MINUS_DST_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="775"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ONE_MINUS_SRC_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="771"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ONE_MINUS_SRC_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="769"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5383"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OR_INVERTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5389"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OR_REVERSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5387"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OUT_OF_MEMORY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1285"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PACK_ALIGNMENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3333"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE4_R5_G6_B5_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35730"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE4_RGB5_A1_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35732"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE4_RGB8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35728"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE4_RGBA4_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35731"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE4_RGBA8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35729"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE8_R5_G6_B5_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35735"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE8_RGB5_A1_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35737"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE8_RGB8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35733"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE8_RGBA4_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35736"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PALETTE8_RGBA8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35734"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PERSPECTIVE_CORRECTION_HINT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_FADE_THRESHOLD_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33064"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2833"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SMOOTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2832"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SMOOTH_HINT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3153"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POLYGON_OFFSET_FILL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32823"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POLYGON_SMOOTH_HINT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3155"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POSITION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4611"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PROJECTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5889"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_QUADRATIC_ATTENUATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4617"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RED_BITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3410"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7937"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_REPEAT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10497"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_REPLACE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7681"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RESCALE_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32826"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6407"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGBA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6408"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SAMPLE_ALPHA_TO_COVERAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32926"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SAMPLE_ALPHA_TO_ONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32927"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SAMPLE_COVERAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32928"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SCISSOR_TEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3089"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SET"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5391"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SHININESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5633"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SHORT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5122"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SMOOTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7425"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SMOOTH_LINE_WIDTH_RANGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2850"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SMOOTH_POINT_SIZE_RANGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2834"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SPECULAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4610"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SPOT_CUTOFF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4614"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SPOT_DIRECTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4612"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SPOT_EXPONENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4613"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="770"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC_ALPHA_SATURATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="776"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="768"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STACK_OVERFLOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1283"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STACK_UNDERFLOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1284"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_BITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3415"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_BUFFER_BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_TEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2960"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SUBPIXEL_BITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3408"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5890"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE0"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33984"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33985"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33994"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33995"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33996"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE13"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33997"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE14"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33998"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE15"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33999"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE16"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE17"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE18"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34002"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE19"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34003"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33986"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE20"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34004"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE21"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34005"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE22"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34006"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE23"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34007"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE24"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34008"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE25"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34009"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE26"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34010"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE27"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34011"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE28"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34012"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE29"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34013"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33987"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE30"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34014"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE31"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34015"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33988"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33989"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33990"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33991"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33992"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33993"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_2D"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3553"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_COORD_ARRAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32888"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_ENV"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8960"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_ENV_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8705"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_ENV_MODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8704"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_MAG_FILTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10240"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_MIN_FILTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10241"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_WRAP_S"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10242"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_WRAP_T"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10243"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TRIANGLES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TRIANGLE_FAN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TRIANGLE_STRIP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TRUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_UNPACK_ALIGNMENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3317"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_UNSIGNED_BYTE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5121"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_UNSIGNED_SHORT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5123"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_UNSIGNED_SHORT_4_4_4_4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32819"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_UNSIGNED_SHORT_5_5_5_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32820"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_UNSIGNED_SHORT_5_6_5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33635"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VENDOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7936"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VERSION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7938"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VERTEX_ARRAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32884"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_XOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5382"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ZERO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GLES10Ext"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GLES10Ext"
+ type="android.opengl.GLES10Ext"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="glQueryMatrixxOES"
+ return="int"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mantissa" type="int[]">
+</parameter>
+<parameter name="mantissaOffset" type="int">
+</parameter>
+<parameter name="exponent" type="int[]">
+</parameter>
+<parameter name="exponentOffset" type="int">
+</parameter>
+</method>
+<method name="glQueryMatrixxOES"
+ return="int"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mantissa" type="java.nio.IntBuffer">
+</parameter>
+<parameter name="exponent" type="java.nio.IntBuffer">
+</parameter>
+</method>
+</class>
+<class name="GLES11"
+ extends="android.opengl.GLES10"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GLES11"
+ type="android.opengl.GLES11"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="glBindBuffer"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="buffer" type="int">
+</parameter>
+</method>
+<method name="glBufferData"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="data" type="java.nio.Buffer">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="glBufferSubData"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="data" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glClipPlanef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glClipPlanef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glClipPlanex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glClipPlanex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glColor4ub"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="byte">
+</parameter>
+<parameter name="green" type="byte">
+</parameter>
+<parameter name="blue" type="byte">
+</parameter>
+<parameter name="alpha" type="byte">
+</parameter>
+</method>
+<method name="glColorPointer"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDeleteBuffers"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="buffers" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDeleteBuffers"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="buffers" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glDrawElements"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGenBuffers"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="buffers" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGenBuffers"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="buffers" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetBooleanv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="boolean[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetBooleanv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetBufferParameteriv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetBufferParameteriv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetClipPlanef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetClipPlanef"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetClipPlanex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetClipPlanex"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetFixedv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetFixedv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetFloatv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetFloatv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetLightfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetLightfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetLightxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetLightxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetMaterialfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetMaterialfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetMaterialxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetMaterialxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexEnvfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexEnvfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetTexEnviv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexEnviv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexEnvxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexEnvxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexParameterfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexParameterfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetTexParameteriv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexParameteriv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexParameterxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexParameterxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glIsBuffer"
+ return="boolean"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="buffer" type="int">
+</parameter>
+</method>
+<method name="glIsEnabled"
+ return="boolean"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cap" type="int">
+</parameter>
+</method>
+<method name="glIsTexture"
+ return="boolean"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texture" type="int">
+</parameter>
+</method>
+<method name="glNormalPointer"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glPointParameterf"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glPointParameterfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glPointParameterfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glPointParameterx"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glPointParameterxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glPointParameterxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glPointSizePointerOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="pointer" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glTexCoordPointer"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexEnvi"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexEnviv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexEnviv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glTexParameterfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexParameterfv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glTexParameteri"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexParameteriv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexParameteriv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glTexParameterxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexParameterxv"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glVertexPointer"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<field name="GL_ACTIVE_TEXTURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34016"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ADD_SIGNED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34164"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALPHA_SCALE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3356"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALPHA_TEST_FUNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3009"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ALPHA_TEST_REF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3010"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ARRAY_BUFFER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34962"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ARRAY_BUFFER_BINDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34964"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_DST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3040"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_SRC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3041"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BUFFER_ACCESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35003"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BUFFER_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34660"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BUFFER_USAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34661"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLIENT_ACTIVE_TEXTURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34017"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLIP_PLANE0"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12288"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLIP_PLANE1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12289"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLIP_PLANE2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12290"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLIP_PLANE3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12291"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLIP_PLANE4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12292"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CLIP_PLANE5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12293"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_ARRAY_BUFFER_BINDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34968"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_ARRAY_POINTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32912"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_ARRAY_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32897"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_ARRAY_STRIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32899"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_ARRAY_TYPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32898"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_CLEAR_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3106"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_WRITEMASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3107"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COMBINE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34160"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COMBINE_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34162"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COMBINE_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34161"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CONSTANT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34166"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COORD_REPLACE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34914"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CULL_FACE_MODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2885"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CURRENT_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2816"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CURRENT_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2818"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CURRENT_TEXTURE_COORDS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2819"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_CLEAR_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2931"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_FUNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2932"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_RANGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2928"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_WRITEMASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2930"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DOT3_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34478"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DOT3_RGBA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34479"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DYNAMIC_DRAW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35048"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ELEMENT_ARRAY_BUFFER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34963"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ELEMENT_ARRAY_BUFFER_BINDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34965"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRONT_FACE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2886"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_GENERATE_MIPMAP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33169"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_GENERATE_MIPMAP_HINT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33170"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INTERPOLATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34165"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LINE_WIDTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2849"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_LOGIC_OP_MODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3056"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_MODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2976"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_CLIP_PLANES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3378"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MODELVIEW_MATRIX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2982"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35213"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MODELVIEW_STACK_DEPTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2979"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NORMAL_ARRAY_BUFFER_BINDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34967"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NORMAL_ARRAY_POINTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32911"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NORMAL_ARRAY_STRIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32895"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NORMAL_ARRAY_TYPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32894"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OPERAND0_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34200"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OPERAND0_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OPERAND1_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34201"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OPERAND1_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34193"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OPERAND2_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34202"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_OPERAND2_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34194"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_DISTANCE_ATTENUATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33065"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_FADE_THRESHOLD_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33064"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2833"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35743"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE_ARRAY_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35740"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE_ARRAY_POINTER_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35212"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE_ARRAY_STRIDE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35211"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE_ARRAY_TYPE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35210"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE_MAX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33063"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SIZE_MIN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33062"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POINT_SPRITE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34913"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POLYGON_OFFSET_FACTOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32824"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_POLYGON_OFFSET_UNITS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10752"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PREVIOUS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34168"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PRIMARY_COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34167"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PROJECTION_MATRIX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2983"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35214"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PROJECTION_STACK_DEPTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2980"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGB_SCALE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34163"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SAMPLES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32937"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SAMPLE_BUFFERS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32936"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SAMPLE_COVERAGE_INVERT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32939"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SAMPLE_COVERAGE_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32938"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SCISSOR_BOX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3088"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SHADE_MODEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2900"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC0_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34184"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC0_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34176"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC1_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34185"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC1_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34177"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC2_ALPHA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34186"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SRC2_RGB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34178"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STATIC_DRAW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35044"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_CLEAR_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2961"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_FAIL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2964"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_FUNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2962"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_PASS_DEPTH_FAIL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2965"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_PASS_DEPTH_PASS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2966"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_REF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2967"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_VALUE_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2963"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_WRITEMASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2968"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_SUBTRACT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34023"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_BINDING_2D"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32873"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34970"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_COORD_ARRAY_POINTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32914"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_COORD_ARRAY_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32904"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_COORD_ARRAY_STRIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32906"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_COORD_ARRAY_TYPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32905"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_MATRIX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2984"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35215"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_STACK_DEPTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2981"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VERTEX_ARRAY_BUFFER_BINDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34966"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VERTEX_ARRAY_POINTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32910"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VERTEX_ARRAY_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32890"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VERTEX_ARRAY_STRIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32892"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VERTEX_ARRAY_TYPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32891"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_VIEWPORT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2978"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WRITE_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GLES11Ext"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GLES11Ext"
+ type="android.opengl.GLES11Ext"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="glAlphaFuncxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="func" type="int">
+</parameter>
+<parameter name="ref" type="int">
+</parameter>
+</method>
+<method name="glBindFramebufferOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="framebuffer" type="int">
+</parameter>
+</method>
+<method name="glBindRenderbufferOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="renderbuffer" type="int">
+</parameter>
+</method>
+<method name="glBlendEquationOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="glBlendEquationSeparateOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modeRGB" type="int">
+</parameter>
+<parameter name="modeAlpha" type="int">
+</parameter>
+</method>
+<method name="glBlendFuncSeparateOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="srcRGB" type="int">
+</parameter>
+<parameter name="dstRGB" type="int">
+</parameter>
+<parameter name="srcAlpha" type="int">
+</parameter>
+<parameter name="dstAlpha" type="int">
+</parameter>
+</method>
+<method name="glCheckFramebufferStatusOES"
+ return="int"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+</method>
+<method name="glClearColorxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="int">
+</parameter>
+<parameter name="green" type="int">
+</parameter>
+<parameter name="blue" type="int">
+</parameter>
+<parameter name="alpha" type="int">
+</parameter>
+</method>
+<method name="glClearDepthfOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="depth" type="float">
+</parameter>
+</method>
+<method name="glClearDepthxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="depth" type="int">
+</parameter>
+</method>
+<method name="glClipPlanefOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glClipPlanefOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glClipPlanexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glClipPlanexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="plane" type="int">
+</parameter>
+<parameter name="equation" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glColor4xOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="red" type="int">
+</parameter>
+<parameter name="green" type="int">
+</parameter>
+<parameter name="blue" type="int">
+</parameter>
+<parameter name="alpha" type="int">
+</parameter>
+</method>
+<method name="glCurrentPaletteMatrixOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="matrixpaletteindex" type="int">
+</parameter>
+</method>
+<method name="glDeleteFramebuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="framebuffers" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDeleteFramebuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="framebuffers" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glDeleteRenderbuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="renderbuffers" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDeleteRenderbuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="renderbuffers" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glDepthRangefOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="zNear" type="float">
+</parameter>
+<parameter name="zFar" type="float">
+</parameter>
+</method>
+<method name="glDepthRangexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="zNear" type="int">
+</parameter>
+<parameter name="zFar" type="int">
+</parameter>
+</method>
+<method name="glDrawTexfOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+<parameter name="width" type="float">
+</parameter>
+<parameter name="height" type="float">
+</parameter>
+</method>
+<method name="glDrawTexfvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDrawTexfvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glDrawTexiOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<method name="glDrawTexivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDrawTexivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glDrawTexsOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="short">
+</parameter>
+<parameter name="y" type="short">
+</parameter>
+<parameter name="z" type="short">
+</parameter>
+<parameter name="width" type="short">
+</parameter>
+<parameter name="height" type="short">
+</parameter>
+</method>
+<method name="glDrawTexsvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="short[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDrawTexsvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="java.nio.ShortBuffer">
+</parameter>
+</method>
+<method name="glDrawTexxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<method name="glDrawTexxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glDrawTexxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coords" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glEGLImageTargetRenderbufferStorageOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="image" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glEGLImageTargetTexture2DOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="image" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glFogxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glFogxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glFogxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glFramebufferRenderbufferOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="attachment" type="int">
+</parameter>
+<parameter name="renderbuffertarget" type="int">
+</parameter>
+<parameter name="renderbuffer" type="int">
+</parameter>
+</method>
+<method name="glFramebufferTexture2DOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="attachment" type="int">
+</parameter>
+<parameter name="textarget" type="int">
+</parameter>
+<parameter name="texture" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+</method>
+<method name="glFrustumfOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="float">
+</parameter>
+<parameter name="right" type="float">
+</parameter>
+<parameter name="bottom" type="float">
+</parameter>
+<parameter name="top" type="float">
+</parameter>
+<parameter name="zNear" type="float">
+</parameter>
+<parameter name="zFar" type="float">
+</parameter>
+</method>
+<method name="glFrustumxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="int">
+</parameter>
+<parameter name="right" type="int">
+</parameter>
+<parameter name="bottom" type="int">
+</parameter>
+<parameter name="top" type="int">
+</parameter>
+<parameter name="zNear" type="int">
+</parameter>
+<parameter name="zFar" type="int">
+</parameter>
+</method>
+<method name="glGenFramebuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="framebuffers" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGenFramebuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="framebuffers" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGenRenderbuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="renderbuffers" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGenRenderbuffersOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="n" type="int">
+</parameter>
+<parameter name="renderbuffers" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGenerateMipmapOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+</method>
+<method name="glGetClipPlanefOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetClipPlanefOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetClipPlanexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetClipPlanexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="eqn" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetFixedvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetFixedvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetFramebufferAttachmentParameterivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="attachment" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetFramebufferAttachmentParameterivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="attachment" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetLightxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetLightxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetMaterialxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetMaterialxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetRenderbufferParameterivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetRenderbufferParameterivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexEnvxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexEnvxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexGenfvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexGenfvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glGetTexGenivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexGenivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexGenxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexGenxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glGetTexParameterxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glGetTexParameterxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glIsFramebufferOES"
+ return="boolean"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="framebuffer" type="int">
+</parameter>
+</method>
+<method name="glIsRenderbufferOES"
+ return="boolean"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="renderbuffer" type="int">
+</parameter>
+</method>
+<method name="glLightModelxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glLightModelxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLightModelxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glLightxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glLightxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLightxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="light" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glLineWidthxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+</method>
+<method name="glLoadMatrixxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glLoadMatrixxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glLoadPaletteFromModelViewMatrixOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="glMaterialxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glMaterialxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glMaterialxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="face" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glMatrixIndexPointerOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="pointer" type="java.nio.Buffer">
+</parameter>
+</method>
+<method name="glMultMatrixxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glMultMatrixxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glMultiTexCoord4xOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="s" type="int">
+</parameter>
+<parameter name="t" type="int">
+</parameter>
+<parameter name="r" type="int">
+</parameter>
+<parameter name="q" type="int">
+</parameter>
+</method>
+<method name="glNormal3xOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nx" type="int">
+</parameter>
+<parameter name="ny" type="int">
+</parameter>
+<parameter name="nz" type="int">
+</parameter>
+</method>
+<method name="glOrthofOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="float">
+</parameter>
+<parameter name="right" type="float">
+</parameter>
+<parameter name="bottom" type="float">
+</parameter>
+<parameter name="top" type="float">
+</parameter>
+<parameter name="zNear" type="float">
+</parameter>
+<parameter name="zFar" type="float">
+</parameter>
+</method>
+<method name="glOrthoxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="int">
+</parameter>
+<parameter name="right" type="int">
+</parameter>
+<parameter name="bottom" type="int">
+</parameter>
+<parameter name="top" type="int">
+</parameter>
+<parameter name="zNear" type="int">
+</parameter>
+<parameter name="zFar" type="int">
+</parameter>
+</method>
+<method name="glPointParameterxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glPointParameterxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glPointParameterxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glPointSizexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+</method>
+<method name="glPolygonOffsetxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factor" type="int">
+</parameter>
+<parameter name="units" type="int">
+</parameter>
+</method>
+<method name="glRenderbufferStorageOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="internalformat" type="int">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<method name="glRotatexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="angle" type="int">
+</parameter>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="glSampleCoveragexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+<parameter name="invert" type="boolean">
+</parameter>
+</method>
+<method name="glScalexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="glTexEnvxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexEnvxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexEnvxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glTexGenfOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="float">
+</parameter>
+</method>
+<method name="glTexGenfvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="float[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexGenfvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.FloatBuffer">
+</parameter>
+</method>
+<method name="glTexGeniOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexGenivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexGenivOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glTexGenxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexGenxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexGenxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="coord" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glTexParameterxOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+</method>
+<method name="glTexParameterxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="int[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="glTexParameterxvOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="int">
+</parameter>
+<parameter name="pname" type="int">
+</parameter>
+<parameter name="params" type="java.nio.IntBuffer">
+</parameter>
+</method>
+<method name="glTranslatexOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+<parameter name="y" type="int">
+</parameter>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="glWeightPointerOES"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="stride" type="int">
+</parameter>
+<parameter name="pointer" type="java.nio.Buffer">
+</parameter>
+</method>
+<field name="GL_3DC_XY_AMD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34810"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_3DC_X_AMD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34809"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ATC_RGBA_EXPLICIT_ALPHA_AMD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35987"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34798"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ATC_RGB_AMD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35986"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BGRA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32993"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_DST_ALPHA_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32970"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_DST_RGB_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32968"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_EQUATION_ALPHA_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34877"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_EQUATION_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32777"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_EQUATION_RGB_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32777"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_SRC_ALPHA_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32971"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BLEND_SRC_RGB_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32969"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BUFFER_ACCESS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35003"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BUFFER_MAPPED_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35004"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_BUFFER_MAP_POINTER_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35005"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_COLOR_ATTACHMENT0_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36064"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_CURRENT_PALETTE_MATRIX_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34883"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DECR_WRAP_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34056"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH24_STENCIL8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35056"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_ATTACHMENT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_COMPONENT16_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33189"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_COMPONENT24_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33190"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_COMPONENT32_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33191"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_DEPTH_STENCIL_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34041"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_ETC1_RGB8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36196"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FIXED_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5132"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36049"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36048"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36051"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36050"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_BINDING_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36006"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_COMPLETE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36053"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36054"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36057"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36058"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36055"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36160"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FRAMEBUFFER_UNSUPPORTED_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36061"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FUNC_ADD_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32774"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FUNC_REVERSE_SUBTRACT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32779"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_FUNC_SUBTRACT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32778"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INCR_WRAP_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34055"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_INVALID_FRAMEBUFFER_OPERATION_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1286"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35742"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_INDEX_ARRAY_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34884"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_INDEX_ARRAY_POINTER_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34889"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_INDEX_ARRAY_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34886"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_INDEX_ARRAY_STRIDE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34888"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_INDEX_ARRAY_TYPE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34887"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MATRIX_PALETTE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34880"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34076"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_PALETTE_MATRICES_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34882"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_RENDERBUFFER_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34047"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MAX_VERTEX_UNITS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34468"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MIRRORED_REPEAT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33648"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35213"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NONE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_NORMAL_MAP_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34065"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35214"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_REFLECTION_MAP_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34066"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_ALPHA_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36179"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_BINDING_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36007"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_BLUE_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36178"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_DEPTH_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36180"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_GREEN_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36177"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_HEIGHT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36163"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_INTERNAL_FORMAT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36164"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36161"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_RED_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36176"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_STENCIL_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36181"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RENDERBUFFER_WIDTH_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36162"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGB565_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36194"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGB5_A1_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32855"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGB8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32849"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGBA4_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32854"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_RGBA8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32856"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_ATTACHMENT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36128"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_INDEX1_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36166"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_INDEX4_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36167"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_STENCIL_INDEX8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36168"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_BINDING_CUBE_MAP_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34068"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CROP_RECT_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35741"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34070"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34072"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34074"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CUBE_MAP_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34067"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34069"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34071"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34073"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_GEN_MODE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9472"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_GEN_STR_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35215"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_TEXTURE_MAX_ANISOTROPY_EXT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34046"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_UNSIGNED_INT_24_8_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34042"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WEIGHT_ARRAY_BUFFER_BINDING_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34974"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WEIGHT_ARRAY_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34477"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WEIGHT_ARRAY_POINTER_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34476"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WEIGHT_ARRAY_SIZE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34475"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WEIGHT_ARRAY_STRIDE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34474"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WEIGHT_ARRAY_TYPE_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34473"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GL_WRITE_ONLY_OES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="GLException"
  extends="java.lang.RuntimeException"
  abstract="false"
@@ -95701,7 +106272,7 @@
  abstract="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <method name="divideMessage"
@@ -95710,8 +106281,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="text" type="java.lang.String">
@@ -95723,8 +106294,8 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95734,8 +106305,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="destinationAddress" type="java.lang.String">
@@ -95757,8 +106328,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="destinationAddress" type="java.lang.String">
@@ -95778,8 +106349,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="destinationAddress" type="java.lang.String">
@@ -95800,7 +106371,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95811,7 +106382,7 @@
  value="4"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95822,7 +106393,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95833,7 +106404,7 @@
  value="2"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95844,7 +106415,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95855,7 +106426,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95866,7 +106437,7 @@
  value="5"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95877,7 +106448,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95888,7 +106459,7 @@
  value="7"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95898,14 +106469,14 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="SmsMessage"
  type="android.telephony.gsm.SmsMessage"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -95916,7 +106487,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="messageBody" type="java.lang.CharSequence">
@@ -95931,7 +106502,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="messageBody" type="java.lang.String">
@@ -95946,7 +106517,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="pdu" type="byte[]">
@@ -95959,7 +106530,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95970,7 +106541,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95981,7 +106552,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95992,7 +106563,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96003,7 +106574,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96014,7 +106585,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96025,7 +106596,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96036,7 +106607,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96047,7 +106618,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96058,7 +106629,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96069,7 +106640,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96080,7 +106651,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96091,7 +106662,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96102,7 +106673,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96113,7 +106684,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="scAddress" type="java.lang.String">
@@ -96132,7 +106703,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="scAddress" type="java.lang.String">
@@ -96153,7 +106724,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="pdu" type="java.lang.String">
@@ -96166,7 +106737,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96177,7 +106748,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96188,7 +106759,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96199,7 +106770,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96210,7 +106781,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96221,7 +106792,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96232,7 +106803,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96243,7 +106814,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96254,7 +106825,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96265,7 +106836,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96276,7 +106847,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96287,7 +106858,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96298,7 +106869,7 @@
  value="2"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96309,7 +106880,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96320,7 +106891,7 @@
  value="140"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96331,7 +106902,7 @@
  value="160"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96342,7 +106913,7 @@
  value="153"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96352,7 +106923,7 @@
  abstract="false"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <method name="valueOf"
@@ -96385,14 +106956,14 @@
  abstract="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="SmsMessage.SubmitPdu"
  type="android.telephony.gsm.SmsMessage.SubmitPdu"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -96403,7 +106974,7 @@
  value="null"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96414,7 +106985,7 @@
  value="null"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -134519,6 +145090,170 @@
 </parameter>
 </method>
 </class>
+<class name="AnticipateInterpolator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.animation.Interpolator">
+</implements>
+<constructor name="AnticipateInterpolator"
+ type="android.view.animation.AnticipateInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="AnticipateInterpolator"
+ type="android.view.animation.AnticipateInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tension" type="float">
+</parameter>
+</constructor>
+<constructor name="AnticipateInterpolator"
+ type="android.view.animation.AnticipateInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="getInterpolation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="float">
+</parameter>
+</method>
+</class>
+<class name="AnticipateOvershootInterpolator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.animation.Interpolator">
+</implements>
+<constructor name="AnticipateOvershootInterpolator"
+ type="android.view.animation.AnticipateOvershootInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="AnticipateOvershootInterpolator"
+ type="android.view.animation.AnticipateOvershootInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tension" type="float">
+</parameter>
+</constructor>
+<constructor name="AnticipateOvershootInterpolator"
+ type="android.view.animation.AnticipateOvershootInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tension" type="float">
+</parameter>
+<parameter name="extraTension" type="float">
+</parameter>
+</constructor>
+<constructor name="AnticipateOvershootInterpolator"
+ type="android.view.animation.AnticipateOvershootInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="getInterpolation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="float">
+</parameter>
+</method>
+</class>
+<class name="BounceInterpolator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.animation.Interpolator">
+</implements>
+<constructor name="BounceInterpolator"
+ type="android.view.animation.BounceInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="BounceInterpolator"
+ type="android.view.animation.BounceInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="getInterpolation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="float">
+</parameter>
+</method>
+</class>
 <class name="CycleInterpolator"
  extends="java.lang.Object"
  abstract="false"
@@ -135322,6 +146057,60 @@
 </parameter>
 </method>
 </class>
+<class name="OvershootInterpolator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.animation.Interpolator">
+</implements>
+<constructor name="OvershootInterpolator"
+ type="android.view.animation.OvershootInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="OvershootInterpolator"
+ type="android.view.animation.OvershootInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tension" type="float">
+</parameter>
+</constructor>
+<constructor name="OvershootInterpolator"
+ type="android.view.animation.OvershootInterpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="getInterpolation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="float">
+</parameter>
+</method>
+</class>
 <class name="RotateAnimation"
  extends="android.view.animation.Animation"
  abstract="false"
@@ -151333,6 +162122,17 @@
  visibility="public"
 >
 </method>
+<method name="getCheckItemIds"
+ return="long[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getCheckedItemPosition"
  return="int"
  abstract="false"
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index 0f1ae8e..a7af57c 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -314,7 +314,7 @@
     String8 result;
     AutoMutex lock(&mLock);
     if (mFakeCamera != 0) {
-        mFakeCamera->dump(fd, args);
+        mFakeCamera->dump(fd);
         mParameters.dump(fd, args);
         snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
         result.append(buffer);
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index cb8ab588..96ee502 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -217,7 +217,13 @@
     // allow anyone to use camera
     LOGV("unlock (%p)", getCameraClient()->asBinder().get());
     status_t result = checkPid();
-    if (result == NO_ERROR) mClientPid = 0;
+    if (result == NO_ERROR) {
+        mClientPid = 0;
+
+        // we need to remove the reference so that when app goes
+        // away, the reference count goes to 0.
+        mCameraClient.clear();
+    }
     return result;
 }
 
@@ -894,8 +900,6 @@
 // get preview/capture parameters - key/value pairs
 String8 CameraService::Client::getParameters() const
 {
-    LOGD("getParameters");
-
     Mutex::Autolock lock(mLock);
 
     if (mHardware == 0) {
@@ -903,7 +907,9 @@
         return String8();
     }
 
-    return mHardware->getParameters().flatten();
+    String8 params(mHardware->getParameters().flatten());
+    LOGD("getParameters(%s)", params.string());
+    return params;
 }
 
 void CameraService::Client::postAutoFocus(bool focused)
diff --git a/camera/libcameraservice/FakeCamera.cpp b/camera/libcameraservice/FakeCamera.cpp
index 3592eab..3daf47d 100644
--- a/camera/libcameraservice/FakeCamera.cpp
+++ b/camera/libcameraservice/FakeCamera.cpp
@@ -1,12 +1,39 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
 #define LOG_TAG "FakeCamera"
 #include <utils/Log.h>
 
 #include <string.h>
 #include <stdlib.h>
+#include <utils/String8.h>
+
 #include "FakeCamera.h"
 
+
 namespace android {
 
+// TODO: All this rgb to yuv should probably be in a util class.
+
+// TODO: I think something is wrong in this class because the shadow is kBlue
+// and the square color should alternate between kRed and kGreen. However on the
+// emulator screen these are all shades of gray. Y seems ok but the U and V are
+// probably not.
+
 static int tables_initialized = 0;
 uint8_t *gYTable, *gCbTable, *gCrTable;
 
@@ -389,7 +416,7 @@
 }
 
 
-status_t FakeCamera::dump(int fd, const Vector<String16>& args)
+void FakeCamera::dump(int fd) const
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
@@ -397,7 +424,6 @@
     snprintf(buffer, 255, " width x height (%d x %d), counter (%d), check x-y coordinate(%d, %d)\n", mWidth, mHeight, mCounter, mCheckX, mCheckY);
     result.append(buffer);
     ::write(fd, result.string(), result.size());
-    return NO_ERROR;
 }
 
 
diff --git a/camera/libcameraservice/FakeCamera.h b/camera/libcameraservice/FakeCamera.h
index 77c994c..f7f8803 100644
--- a/camera/libcameraservice/FakeCamera.h
+++ b/camera/libcameraservice/FakeCamera.h
@@ -18,21 +18,37 @@
 #ifndef ANDROID_HARDWARE_FAKECAMERA_H
 #define ANDROID_HARDWARE_FAKECAMERA_H
 
-#include <ui/CameraHardwareInterface.h>
+#include <sys/types.h>
+#include <stdint.h>
 
 namespace android {
 
+/*
+ * FakeCamera is used in the CameraHardwareStub to provide a fake video feed
+ * when the system does not have a camera in hardware.
+ * The fake video is a moving black and white checkerboard background with a
+ * bouncing gray square in the foreground.
+ * This class is not thread-safe.
+ *
+ * TODO: Since the major methods provides a raw/uncompressed video feed, rename
+ * this class to RawVideoSource.
+ */
+
 class FakeCamera {
 public:
     FakeCamera(int width, int height);
     ~FakeCamera();
 
     void setSize(int width, int height);
-    void getNextFrameAsRgb565(uint16_t *buffer);
     void getNextFrameAsYuv422(uint8_t *buffer);
-    status_t dump(int fd, const Vector<String16>& args);
+    // Write to the fd a string representing the current state.
+    void dump(int fd) const;
 
 private:
+    // TODO: remove the uint16_t buffer param everywhere since it is a field of
+    // this class.
+    void getNextFrameAsRgb565(uint16_t *buffer);
+
     void drawSquare(uint16_t *buffer, int x, int y, int size, int color, int shadow);
     void drawCheckerboard(uint16_t *buffer, int size);
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 849a37d..9b1f0f9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -611,7 +611,7 @@
     private IBinder mToken;
     /*package*/ String mEmbeddedID;
     private Application mApplication;
-    private Intent mIntent;
+    /*package*/ Intent mIntent;
     private ComponentName mComponent;
     /*package*/ ActivityInfo mActivityInfo;
     /*package*/ ActivityThread mMainThread;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d816193..dfa3fa8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -161,7 +161,7 @@
         return metrics;
     }
 
-    Resources getTopLevelResources(String appDir) {
+    Resources getTopLevelResources(String appDir, float applicationScale) {
         synchronized (mPackages) {
             //Log.w(TAG, "getTopLevelResources: " + appDir);
             WeakReference<Resources> wr = mActiveResources.get(appDir);
@@ -181,7 +181,27 @@
                 return null;
             }
             DisplayMetrics metrics = getDisplayMetricsLocked(false);
-            r = new Resources(assets, metrics, getConfiguration());
+            // density used to load resources
+            // scaledDensity is calculated in Resources constructor
+            //
+            boolean usePreloaded = true;
+
+            // TODO: use explicit flag to indicate the compatibility mode.
+            if (applicationScale != 1.0f) {
+                usePreloaded = false;
+                DisplayMetrics newMetrics = new DisplayMetrics();
+                newMetrics.setTo(metrics);
+                float invertedScale = 1.0f / applicationScale;
+                newMetrics.density *= invertedScale;
+                newMetrics.xdpi *= invertedScale;
+                newMetrics.ydpi *= invertedScale;
+                newMetrics.widthPixels *= invertedScale;
+                newMetrics.heightPixels *= invertedScale;
+                metrics = newMetrics;
+            }
+            //Log.i(TAG, "Resource:" + appDir + ", density " + newMetrics.density + ", orig density:" +
+            //      metrics.density);
+            r = new Resources(assets, metrics, getConfiguration(), usePreloaded);
             //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
             // XXX need to remove entries when weak references go away
             mActiveResources.put(appDir, new WeakReference<Resources>(r));
@@ -209,6 +229,8 @@
         private Resources mResources;
         private ClassLoader mClassLoader;
         private Application mApplication;
+        private float mApplicationScale;
+
         private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
             = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
         private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
@@ -241,8 +263,8 @@
                     mSystemContext =
                         ApplicationContext.createSystemContext(mainThread);
                     mSystemContext.getResources().updateConfiguration(
-                            mainThread.getConfiguration(),
-                            mainThread.getDisplayMetricsLocked(false));
+                             mainThread.getConfiguration(),
+                             mainThread.getDisplayMetricsLocked(false));
                     //Log.i(TAG, "Created system resources "
                     //        + mSystemContext.getResources() + ": "
                     //        + mSystemContext.getResources().getConfiguration());
@@ -250,6 +272,8 @@
                 mClassLoader = mSystemContext.getClassLoader();
                 mResources = mSystemContext.getResources();
             }
+
+            mApplicationScale = -1.0f;
         }
 
         public PackageInfo(ActivityThread activityThread, String name,
@@ -268,6 +292,7 @@
             mIncludeCode = true;
             mClassLoader = systemContext.getClassLoader();
             mResources = systemContext.getResources();
+            mApplicationScale = systemContext.getApplicationScale();
         }
 
         public String getPackageName() {
@@ -278,6 +303,47 @@
             return mSecurityViolation;
         }
 
+        public float getApplicationScale() {
+            if (mApplicationScale > 0.0f) {
+                return mApplicationScale;
+            }
+            DisplayMetrics metrics = mActivityThread.getDisplayMetricsLocked(false);
+            // Find out the density scale (relative to 160) of the supported density  that
+            // is closest to the system's density.
+            try {
+                ApplicationInfo ai = getPackageManager().getApplicationInfo(
+                        mPackageName, PackageManager.GET_SUPPORTS_DENSITIES);
+
+                float appScale = -1.0f;
+                if (ai.supportsDensities != null) {
+                    // TODO: precompute this in DisplayMetrics
+                    float systemDensityDpi = metrics.density * DisplayMetrics.DEFAULT_DENSITY;
+                    int minDiff = Integer.MAX_VALUE;
+                    for (int density : ai.supportsDensities) {
+                        int tmpDiff = (int) Math.abs(systemDensityDpi - density);
+                        if (tmpDiff == 0) {
+                            appScale = 1.0f;
+                            break;
+                        }
+                        // prefer higher density (appScale>1.0), unless that's only option.
+                        if (tmpDiff < minDiff && appScale < 1.0f) {
+                            appScale = systemDensityDpi / density;
+                            minDiff = tmpDiff;
+                        }
+                    }
+                }
+                if (appScale < 0.0f) {
+                    mApplicationScale = metrics.density;
+                } else {
+                    mApplicationScale = appScale;
+                }
+            } catch (RemoteException e) {
+                throw new AssertionError(e);
+            }
+            if (localLOGV) Log.v(TAG, "appScale=" + mApplicationScale + ", pkg=" + mPackageName);
+            return mApplicationScale;
+        }
+
         /**
          * Gets the array of shared libraries that are listed as
          * used by the given package.
@@ -435,7 +501,7 @@
 
         public Resources getResources(ActivityThread mainThread) {
             if (mResources == null) {
-                mResources = mainThread.getTopLevelResources(mResDir);
+                mResources = mainThread.getTopLevelResources(mResDir, getApplicationScale());
             }
             return mResources;
         }
@@ -1689,7 +1755,7 @@
 
                     r.packageInfo = getPackageInfoNoCheck(
                             r.activityInfo.applicationInfo);
-                    handleLaunchActivity(r);
+                    handleLaunchActivity(r, null);
                 } break;
                 case RELAUNCH_ACTIVITY: {
                     ActivityRecord r = (ActivityRecord)msg.obj;
@@ -2109,7 +2175,7 @@
                     + ", comp=" + name
                     + ", token=" + token);
         }
-        return performLaunchActivity(r);
+        return performLaunchActivity(r, null);
     }
 
     public final Activity getActivity(IBinder token) {
@@ -2159,7 +2225,7 @@
         queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
     }
 
-    private final Activity performLaunchActivity(ActivityRecord r) {
+    private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
         // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
 
         ActivityInfo aInfo = r.activityInfo;
@@ -2219,6 +2285,9 @@
                         r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances,
                         config);
                 
+                if (customIntent != null) {
+                    activity.mIntent = customIntent;
+                }
                 r.lastNonConfigurationInstance = null;
                 r.lastNonConfigurationChildInstances = null;
                 activity.mStartedActivity = false;
@@ -2274,14 +2343,14 @@
         return activity;
     }
 
-    private final void handleLaunchActivity(ActivityRecord r) {
+    private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
 
         if (localLOGV) Log.v(
             TAG, "Handling launch of " + r);
-        Activity a = performLaunchActivity(r);
+        Activity a = performLaunchActivity(r, customIntent);
 
         if (a != null) {
             handleResumeActivity(r.token, false, r.isForward);
@@ -3243,6 +3312,7 @@
         }
         
         r.activity.mConfigChangeFlags |= configChanges;
+        Intent currentIntent = r.activity.mIntent;
         
         Bundle savedState = null;
         if (!r.paused) {
@@ -3275,7 +3345,7 @@
             r.state = savedState;
         }
         
-        handleLaunchActivity(r);
+        handleLaunchActivity(r, currentIntent);
     }
 
     private final void handleRequestThumbnail(IBinder token) {
@@ -3492,6 +3562,9 @@
             int sqliteReleased = SQLiteDatabase.releaseMemory();
             EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
         }
+        
+        // Ask graphics to free up as much as possible (font/image caches)
+        Canvas.freeCaches();
 
         BinderInternal.forceGc("mem");
     }
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 55fce49..a1f5a58 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -550,6 +550,19 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public float getApplicationScale() {
+        if (mPackageInfo != null) {
+            return mPackageInfo.getApplicationScale();
+        } else {
+            // same as system density
+            return 1.0f;
+        }
+    }
+
     @Override
     public void setWallpaper(Bitmap bitmap) throws IOException  {
         try {
@@ -2008,9 +2021,11 @@
             if (app.packageName.equals("system")) {
                 return mContext.mMainThread.getSystemContext().getResources();
             }
+            ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);
             Resources r = mContext.mMainThread.getTopLevelResources(
                     app.uid == Process.myUid() ? app.sourceDir
-                    : app.publicSourceDir);
+                    : app.publicSourceDir,
+                    pi.getApplicationScale());
             if (r != null) {
                 return r;
             }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 1bed706..cb660c7 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -440,9 +440,13 @@
 
     @Override
     public String toString() {
-        return "PendingIntent{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " target " + (mTarget != null ? mTarget.asBinder() : null) + "}";
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("PendingIntent{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(": ");
+        sb.append(mTarget != null ? mTarget.asBinder() : null);
+        sb.append('}');
+        return sb.toString();
     }
     
     public int describeContents() {
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index a0cdb63..2d2e710 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -16,24 +16,23 @@
 
 package android.app;
 
+import static android.app.SuggestionsAdapter.getColumnString;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.server.search.SearchableInfo;
 import android.speech.RecognizerIntent;
@@ -45,25 +44,26 @@
 import android.util.Log;
 import android.view.Gravity;
 import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.AutoCompleteTextView;
 import android.widget.Button;
-import android.widget.CursorAdapter;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
 import android.widget.TextView;
-import android.widget.WrapperListAdapter;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView.OnItemSelectedListener;
 
-import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.WeakHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
@@ -75,59 +75,70 @@
 public class SearchDialog extends Dialog implements OnItemClickListener, OnItemSelectedListener {
 
     // Debugging support
-    final static String LOG_TAG = "SearchDialog";
-    private static final int DBG_LOG_TIMING = 0;
-    final static int DBG_JAM_THREADING = 0;
+    private static final boolean DBG = false;
+    private static final String LOG_TAG = "SearchDialog";
+    private static final boolean DBG_LOG_TIMING = false;
 
-    // interaction with runtime
-    IntentFilter mCloseDialogsFilter;
-    IntentFilter mPackageFilter;
-    
     private static final String INSTANCE_KEY_COMPONENT = "comp";
     private static final String INSTANCE_KEY_APPDATA = "data";
     private static final String INSTANCE_KEY_GLOBALSEARCH = "glob";
     private static final String INSTANCE_KEY_DISPLAY_QUERY = "dQry";
     private static final String INSTANCE_KEY_DISPLAY_SEL_START = "sel1";
     private static final String INSTANCE_KEY_DISPLAY_SEL_END = "sel2";
-    private static final String INSTANCE_KEY_USER_QUERY = "uQry";
-    private static final String INSTANCE_KEY_SUGGESTION_QUERY = "sQry";
     private static final String INSTANCE_KEY_SELECTED_ELEMENT = "slEl";
     private static final int INSTANCE_SELECTED_BUTTON = -2;
     private static final int INSTANCE_SELECTED_QUERY = -1;
-
+    
+    private static final int SEARCH_PLATE_LEFT_PADDING_GLOBAL = 12;
+    private static final int SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL = 7;
+    
+    // interaction with runtime
+    private IntentFilter mCloseDialogsFilter;
+    private IntentFilter mPackageFilter;
+    
     // views & widgets
     private TextView mBadgeLabel;
-    private AutoCompleteTextView mSearchTextField;
+    private ImageView mAppIcon;
+    private SearchAutoComplete mSearchAutoComplete;
     private Button mGoButton;
     private ImageButton mVoiceButton;
+    private View mSearchPlate;
 
     // interaction with searchable application
+    private SearchableInfo mSearchable;
     private ComponentName mLaunchComponent;
     private Bundle mAppSearchData;
     private boolean mGlobalSearchMode;
     private Context mActivityContext;
+    
+    // stack of previous searchables, to support the BACK key after
+    // SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.
+    // The top of the stack (= previous searchable) is the last element of the list,
+    // since adding and removing is efficient at the end of an ArrayList.
+    private ArrayList<ComponentName> mPreviousComponents;
 
-    // interaction with the search manager service
-    private SearchableInfo mSearchable;
-    
-    // support for suggestions 
-    private String mUserQuery = null;
-    private int mUserQuerySelStart;
-    private int mUserQuerySelEnd;
-    private boolean mLeaveJammedQueryOnRefocus = false;
-    private String mPreviousSuggestionQuery = null;
-    private int mPresetSelection = -1;
-    private String mSuggestionAction = null;
-    private Uri mSuggestionData = null;
-    private String mSuggestionQuery = null;
-    
     // For voice searching
     private Intent mVoiceWebSearchIntent;
     private Intent mVoiceAppSearchIntent;
 
     // support for AutoCompleteTextView suggestions display
     private SuggestionsAdapter mSuggestionsAdapter;
-
+    
+    // Whether to rewrite queries when selecting suggestions
+    // TODO: This is disabled because of problems with persistent selections
+    // causing non-user-initiated rewrites.
+    private static final boolean REWRITE_QUERIES = false;
+    
+    // The query entered by the user. This is not changed when selecting a suggestion
+    // that modifies the contents of the text field. But if the user then edits
+    // the suggestion, the resulting string is saved.
+    private String mUserQuery;
+    
+    // A weak map of drawables we've gotten from other packages, so we don't load them
+    // more than once.
+    private final WeakHashMap<String, Drawable> mOutsideDrawablesCache =
+            new WeakHashMap<String, Drawable>();
+    
     /**
      * Constructor - fires it up and makes it look like the search UI.
      * 
@@ -151,27 +162,35 @@
         setContentView(com.android.internal.R.layout.search_bar);
 
         theWindow.setLayout(ViewGroup.LayoutParams.FILL_PARENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT);
+                // taking up the whole window (even when transparent) is less than ideal,
+                // but necessary to show the popup window until the window manager supports
+                // having windows anchored by their parent but not clipped by them.
+                ViewGroup.LayoutParams.FILL_PARENT);
         WindowManager.LayoutParams lp = theWindow.getAttributes();
-        lp.setTitle("Search Dialog");
         lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE;
         theWindow.setAttributes(lp);
 
         // get the view elements for local access
         mBadgeLabel = (TextView) findViewById(com.android.internal.R.id.search_badge);
-        mSearchTextField = (AutoCompleteTextView) 
+        mSearchAutoComplete = (SearchAutoComplete)
                 findViewById(com.android.internal.R.id.search_src_text);
+        mAppIcon = (ImageView) findViewById(com.android.internal.R.id.search_app_icon);
         mGoButton = (Button) findViewById(com.android.internal.R.id.search_go_btn);
         mVoiceButton = (ImageButton) findViewById(com.android.internal.R.id.search_voice_btn);
+        mSearchPlate = findViewById(com.android.internal.R.id.search_plate);
         
         // attach listeners
-        mSearchTextField.addTextChangedListener(mTextWatcher);
-        mSearchTextField.setOnKeyListener(mTextKeyListener);
+        mSearchAutoComplete.addTextChangedListener(mTextWatcher);
+        mSearchAutoComplete.setOnKeyListener(mTextKeyListener);
+        mSearchAutoComplete.setOnItemClickListener(this);
+        mSearchAutoComplete.setOnItemSelectedListener(this);
         mGoButton.setOnClickListener(mGoButtonClickListener);
         mGoButton.setOnKeyListener(mButtonsKeyListener);
         mVoiceButton.setOnClickListener(mVoiceButtonClickListener);
         mVoiceButton.setOnKeyListener(mButtonsKeyListener);
 
+        mSearchAutoComplete.setSearchDialog(this);
+        
         // pre-hide all the extraneous elements
         mBadgeLabel.setVisibility(View.GONE);
 
@@ -199,7 +218,7 @@
     /**
      * Set up the search dialog
      * 
-     * @param Returns true if search dialog launched, false if not
+     * @return true if search dialog launched, false if not
      */
     public boolean show(String initialQuery, boolean selectInitialQuery,
             ComponentName componentName, Bundle appSearchData, boolean globalSearch) {
@@ -208,75 +227,65 @@
             // in this case, just discard the "show" request
             return true;
         }
-
-        // Get searchable info from search manager and use to set up other elements of UI
-        // Do this first so we can get out quickly if there's nothing to search
-        ISearchManager sms;
-        sms = ISearchManager.Stub.asInterface(ServiceManager.getService(Context.SEARCH_SERVICE));
-        try {
-            mSearchable = sms.getSearchableInfo(componentName, globalSearch);
-        } catch (RemoteException e) {
-            mSearchable = null;
+        
+        // set up the searchable and show the dialog
+        if (!show(componentName, appSearchData, globalSearch)) {
+            return false;
         }
+        
+        // finally, load the user's initial text (which may trigger suggestions)
+        setUserQuery(initialQuery);
+        if (selectInitialQuery) {
+            mSearchAutoComplete.selectAll();
+        }
+        
+        return true;
+    }
+    
+    /**
+     * Sets up the search dialog and shows it.
+     * 
+     * @return <code>true</code> if search dialog launched
+     */
+    private boolean show(ComponentName componentName, Bundle appSearchData, 
+            boolean globalSearch) {
+        
+        if (DBG) { 
+            Log.d(LOG_TAG, "show(" + componentName + ", " 
+                    + appSearchData + ", " + globalSearch + ")");
+        }
+        
+        mSearchable = SearchManager.getSearchableInfo(componentName, globalSearch);
         if (mSearchable == null) {
             // unfortunately, we can't log here.  it would be logspam every time the user
             // clicks the "search" key on a non-search app
             return false;
         }
         
-        // OK, we're going to show ourselves
-        super.show();
-
-        setupSearchableInfo();
-        
         mLaunchComponent = componentName;
         mAppSearchData = appSearchData;
-        mGlobalSearchMode = globalSearch;
+        // Using globalSearch here is just an optimization, just calling
+        // isDefaultSearchable() should always give the same result.
+        mGlobalSearchMode = globalSearch || SearchManager.isDefaultSearchable(mSearchable); 
+        mActivityContext = mSearchable.getActivityContext(getContext());
+        
+        // show the dialog. this will call onStart().
+        if (!isShowing()) {
+            show();
+        }
 
+        updateUI();
+        
+        return true;
+    }
+    
+    @Override
+    protected void onStart() {
+        super.onStart();
+        
         // receive broadcasts
         getContext().registerReceiver(mBroadcastReceiver, mCloseDialogsFilter);
         getContext().registerReceiver(mBroadcastReceiver, mPackageFilter);
-        
-        // configure the autocomplete aspects of the input box
-        mSearchTextField.setOnItemClickListener(this);
-        mSearchTextField.setOnItemSelectedListener(this);
-
-        // This conversion is necessary to force a preload of the EditText and thus force
-        // suggestions to be presented (even for an empty query)
-        if (initialQuery == null) {
-            initialQuery = "";     // This forces the preload to happen, triggering suggestions
-        }
-
-        // attach the suggestions adapter, if suggestions are available
-        // The existence of a suggestions authority is the proxy for "suggestions available here"
-        if (mSearchable.getSuggestAuthority() == null) {
-            mSuggestionsAdapter = null;
-            mSearchTextField.setAdapter(mSuggestionsAdapter);
-            mSearchTextField.setText(initialQuery);
-        } else {
-            mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable, 
-                    mSearchTextField);
-            mSearchTextField.setAdapter(mSuggestionsAdapter);
-
-            // finally, load the user's initial text (which may trigger suggestions)
-            mSuggestionsAdapter.setNonUserQuery(false);
-            mSearchTextField.setText(initialQuery);
-        }
-        
-        if (selectInitialQuery) {
-            mSearchTextField.selectAll();
-        } else {
-            mSearchTextField.setSelection(initialQuery.length());
-        }
-        return true;
-    }
-
-    /**
-     * The default show() for this Dialog is not supported.
-     */
-    @Override
-    public void show() {
-        return;
     }
 
     /**
@@ -289,6 +298,8 @@
     public void onStop() {
         super.onStop();
         
+        // TODO: Removing the listeners means that they never get called, since 
+        // Dialog.dismissDialog() calls onStop() before sendDismissMessage().
         setOnCancelListener(null);
         setOnDismissListener(null);
         
@@ -299,26 +310,36 @@
             // This is OK - it just means we didn't have any registered
         }
         
-        // close any leftover cursor
-        if (mSuggestionsAdapter != null) {
-            mSuggestionsAdapter.changeCursor(null);
-        }
+        closeSuggestionsAdapter();
         
         // dump extra memory we're hanging on to
         mLaunchComponent = null;
         mAppSearchData = null;
         mSearchable = null;
-        mSuggestionAction = null;
-        mSuggestionData = null;
-        mSuggestionQuery = null;
         mActivityContext = null;
-        mPreviousSuggestionQuery = null;
         mUserQuery = null;
+        mPreviousComponents = null;
+    }
+    
+    /**
+     * Closes and gets rid of the suggestions adapter.
+     */
+    private void closeSuggestionsAdapter() {
+        // remove the adapter from the autocomplete first, to avoid any updates
+        // when we drop the cursor
+        mSearchAutoComplete.setAdapter((SuggestionsAdapter)null);
+        // close any leftover cursor
+        if (mSuggestionsAdapter != null) {
+            mSuggestionsAdapter.changeCursor(null);
+        }
+        mSuggestionsAdapter = null;
     }
     
     /**
      * Save the minimal set of data necessary to recreate the search
      * 
+     * TODO: go through this and make sure that it saves everything that is needed
+     * 
      * @return A bundle with the state of the dialog.
      */
     @Override
@@ -331,16 +352,14 @@
         bundle.putBoolean(INSTANCE_KEY_GLOBALSEARCH, mGlobalSearchMode);
         
         // UI state
-        bundle.putString(INSTANCE_KEY_DISPLAY_QUERY, mSearchTextField.getText().toString());
-        bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_START, mSearchTextField.getSelectionStart());
-        bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_END, mSearchTextField.getSelectionEnd());
-        bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery);
-        bundle.putString(INSTANCE_KEY_SUGGESTION_QUERY, mPreviousSuggestionQuery);
+        bundle.putString(INSTANCE_KEY_DISPLAY_QUERY, mSearchAutoComplete.getText().toString());
+        bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_START, mSearchAutoComplete.getSelectionStart());
+        bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_END, mSearchAutoComplete.getSelectionEnd());
         
         int selectedElement = INSTANCE_SELECTED_QUERY;
         if (mGoButton.isFocused()) {
             selectedElement = INSTANCE_SELECTED_BUTTON;
-        } else if (mSearchTextField.isPopupShowing()) {
+        } else if (mSearchAutoComplete.isPopupShowing()) {
             selectedElement = 0; // TODO mSearchTextField.getListSelection()    // 0..n
         }
         bundle.putInt(INSTANCE_KEY_SELECTED_ELEMENT, selectedElement);
@@ -350,6 +369,8 @@
 
     /**
      * Restore the state of the dialog from a previously saved bundle.
+     * 
+     * TODO: go through this and make sure that it saves everything that is saved
      *
      * @param savedInstanceState The state of the dialog previously saved by
      *     {@link #onSaveInstanceState()}.
@@ -365,26 +386,17 @@
         String displayQuery = savedInstanceState.getString(INSTANCE_KEY_DISPLAY_QUERY);
         int querySelStart = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_START, -1);
         int querySelEnd = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_END, -1);
-        String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY);
         int selectedElement = savedInstanceState.getInt(INSTANCE_KEY_SELECTED_ELEMENT);
-        String suggestionQuery = savedInstanceState.getString(INSTANCE_KEY_SUGGESTION_QUERY);
         
         // show the dialog.  skip any show/hide animation, we want to go fast.
         // send the text that actually generates the suggestions here;  we'll replace the display
         // text as necessary in a moment.
-        if (!show(suggestionQuery, false, launchComponent, appSearchData, globalSearch)) {
+        if (!show(displayQuery, false, launchComponent, appSearchData, globalSearch)) {
             // for some reason, we couldn't re-instantiate
             return;
         }
         
-        if (mSuggestionsAdapter != null) {
-            mSuggestionsAdapter.setNonUserQuery(true);
-        }
-        mSearchTextField.setText(displayQuery);
-        // TODO because the new query is (not) processed in another thread, we can't just
-        // take away this flag (yet).  The better solution here is going to require a new API
-        // in AutoCompleteTextView which allows us to change the text w/o changing the suggestions.
-//      mSuggestionsAdapter.setNonUserQuery(false);
+        mSearchAutoComplete.setText(displayQuery);
         
         // clean up the selection state
         switch (selectedElement) {
@@ -395,40 +407,38 @@
             break;
         case INSTANCE_SELECTED_QUERY:
             if (querySelStart >= 0 && querySelEnd >= 0) {
-                mSearchTextField.requestFocus();
-                mSearchTextField.setSelection(querySelStart, querySelEnd);
+                mSearchAutoComplete.requestFocus();
+                mSearchAutoComplete.setSelection(querySelStart, querySelEnd);
             }
             break;
         default:
-            // defer selecting a list element until suggestion list appears
-            mPresetSelection = selectedElement;
-            // TODO mSearchTextField.setListSelection(selectedElement)
+            // TODO: defer selecting a list element until suggestion list appears
+//            mSearchAutoComplete.setListSelection(selectedElement)
             break;
         }
     }
     
     /**
-     * Hook for updating layout on a rotation
-     * 
+     * Called after resources have changed, e.g. after screen rotation or locale change.
      */
     public void onConfigurationChanged(Configuration newConfig) {
         if (isShowing()) {
             // Redraw (resources may have changed)
             updateSearchButton();
+            updateSearchAppIcon();
             updateSearchBadge();
             updateQueryHint();
         } 
     }
-
+    
     /**
-     * Use SearchableInfo record (from search manager service) to preconfigure the UI in various
-     * ways.
+     * Update the UI according to the info in the current value of {@link #mSearchable}.
      */
-    private void setupSearchableInfo() {
+    private void updateUI() {
         if (mSearchable != null) {
-            mActivityContext = mSearchable.getActivityContext(getContext());
-            
+            updateSearchAutoComplete();
             updateSearchButton();
+            updateSearchAppIcon();
             updateSearchBadge();
             updateQueryHint();
             updateVoiceButton();
@@ -449,24 +459,38 @@
                     inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
                 }
             }
-            mSearchTextField.setInputType(inputType);
-            mSearchTextField.setImeOptions(mSearchable.getImeOptions());
+            mSearchAutoComplete.setInputType(inputType);
+            mSearchAutoComplete.setImeOptions(mSearchable.getImeOptions());
+        }
+    }
+    
+    /**
+     * Updates the auto-complete text view.
+     */
+    private void updateSearchAutoComplete() {
+        // close any existing suggestions adapter
+        closeSuggestionsAdapter();
+        
+        mSearchAutoComplete.setDropDownAnimationStyle(0); // no animation
+        mSearchAutoComplete.setThreshold(0);  // always allow zero-query suggestions
+
+        if (mGlobalSearchMode) {
+            mSearchAutoComplete.setDropDownAlwaysVisible(true);  // fill space until results come in
+            mSearchAutoComplete.setDropDownDismissedOnCompletion(false);
+        } else {
+            mSearchAutoComplete.setDropDownAlwaysVisible(false);
+            mSearchAutoComplete.setDropDownDismissedOnCompletion(true);
+        }
+
+        // attach the suggestions adapter, if suggestions are available
+        // The existence of a suggestions authority is the proxy for "suggestions available here"
+        if (mSearchable.getSuggestAuthority() != null) {
+            mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable, 
+                    mOutsideDrawablesCache);
+            mSearchAutoComplete.setAdapter(mSuggestionsAdapter);
         }
     }
 
-    /**
-     * The list of installed packages has just changed.  This means that our current context
-     * may no longer be valid.  This would only happen if a package is installed/removed exactly
-     * when the search bar is open.  So for now we're just going to close the search
-     * bar.  
-     * 
-     * Anything fancier would require some checks to see if the user's context was still valid.
-     * Which would be messier.
-     */
-    public void onPackageListChange() {
-        cancel();
-    }
-    
     /**    
      * Update the text in the search button.  Note: This is deprecated functionality, for 
      * 1.0 compatibility only.
@@ -481,26 +505,56 @@
             iconLabel = getContext().getResources().
                     getDrawable(com.android.internal.R.drawable.ic_btn_search);
         }
-        mGoButton.setText(textLabel);  
+        mGoButton.setText(textLabel);
         mGoButton.setCompoundDrawablesWithIntrinsicBounds(iconLabel, null, null, null);
     }
     
+    private void updateSearchAppIcon() {
+        if (mGlobalSearchMode) {
+            mAppIcon.setImageResource(0);
+            mAppIcon.setVisibility(View.GONE);
+            mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_GLOBAL,
+                    mSearchPlate.getPaddingTop(),
+                    mSearchPlate.getPaddingRight(),
+                    mSearchPlate.getPaddingBottom());
+        } else {
+            PackageManager pm = getContext().getPackageManager();
+            Drawable icon = null;
+            try {
+                ActivityInfo info = pm.getActivityInfo(mLaunchComponent, 0);
+                icon = pm.getApplicationIcon(info.applicationInfo);
+                if (DBG) Log.d(LOG_TAG, "Using app-specific icon");
+            } catch (NameNotFoundException e) {
+                icon = pm.getDefaultActivityIcon();
+                Log.w(LOG_TAG, mLaunchComponent + " not found, using generic app icon");
+            }
+            mAppIcon.setImageDrawable(icon);
+            mAppIcon.setVisibility(View.VISIBLE);
+            mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL,
+                    mSearchPlate.getPaddingTop(),
+                    mSearchPlate.getPaddingRight(),
+                    mSearchPlate.getPaddingBottom());
+        }
+    }
+
     /**
-     * Setup the search "Badge" if request by mode flags.
+     * Setup the search "Badge" if requested by mode flags.
      */
     private void updateSearchBadge() {
         // assume both hidden
         int visibility = View.GONE;
         Drawable icon = null;
-        String text = null;
+        CharSequence text = null;
         
         // optionally show one or the other.
         if (mSearchable.mBadgeIcon) {
             icon = mActivityContext.getResources().getDrawable(mSearchable.getIconId());
             visibility = View.VISIBLE;
+            if (DBG) Log.d(LOG_TAG, "Using badge icon: " + mSearchable.getIconId());
         } else if (mSearchable.mBadgeLabel) {
             text = mActivityContext.getResources().getText(mSearchable.getLabelId()).toString();
             visibility = View.VISIBLE;
+            if (DBG) Log.d(LOG_TAG, "Using badge label: " + mSearchable.getLabelId());
         }
         
         mBadgeLabel.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
@@ -520,7 +574,7 @@
                     hint = mActivityContext.getString(hintId);
                 }
             }
-            mSearchTextField.setHint(hint);
+            mSearchAutoComplete.setHint(hint);
         }
     }
 
@@ -548,63 +602,129 @@
         mVoiceButton.setVisibility(visibility);
     }
     
+    /*
+     * Menu.
+     */
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Show search settings menu item if anyone handles the intent for it
+        Intent settingsIntent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS);
+        PackageManager pm = getContext().getPackageManager();
+        ActivityInfo activityInfo = settingsIntent.resolveActivityInfo(pm, 0);
+        if (activityInfo != null) {
+            settingsIntent.setClassName(activityInfo.applicationInfo.packageName,
+                    activityInfo.name);
+            String label = getActivityLabel(activityInfo);
+            menu.add(Menu.NONE, Menu.NONE, Menu.NONE, label)
+                    .setIcon(android.R.drawable.ic_menu_preferences)
+                    .setAlphabeticShortcut('P')
+                    .setIntent(settingsIntent);
+            return true;
+        }
+        return super.onCreateOptionsMenu(menu);
+    }
+    
+    // TODO: shouldn't this be in PackageManager?
+    private String getActivityLabel(ActivityInfo activityInfo) {
+        PackageManager pm = getContext().getPackageManager();
+        try {
+            int labelRes = activityInfo.labelRes;
+            if (labelRes == 0) {
+                return null;
+            }
+            Resources r = pm.getResourcesForApplication(activityInfo.applicationInfo);
+            return r.getString(labelRes);
+        } catch (NameNotFoundException ex) {
+            return null;
+        }
+    }
+    
     /**
      * Listeners of various types
      */
 
     /**
+     * {@link Dialog#onTouchEvent(MotionEvent)} will cancel the dialog only when the
+     * touch is outside the window. But the window includes space for the drop-down,
+     * so we also cancel on taps outside the search bar when the drop-down is not showing.
+     */
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // cancel if the drop-down is not showing and the touch event was outside the search plate
+        if (!mSearchAutoComplete.isPopupShowing() && isOutOfBounds(mSearchPlate, event)) {
+            if (DBG) Log.d(LOG_TAG, "Pop-up not showing and outside of search plate.");
+            cancel();
+            return true;
+        }
+        // Let Dialog handle events outside the window while the pop-up is showing.
+        return super.onTouchEvent(event);
+    }
+    
+    private boolean isOutOfBounds(View v, MotionEvent event) {
+        final int x = (int) event.getX();
+        final int y = (int) event.getY();
+        final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop();
+        return (x < -slop) || (y < -slop)
+                || (x > (v.getWidth()+slop))
+                || (y > (v.getHeight()+slop));
+    }
+    
+    /**
      * Dialog's OnKeyListener implements various search-specific functionality
      *
      * @param keyCode This is the keycode of the typed key, and is the same value as
-     * found in the KeyEvent parameter.
+     *        found in the KeyEvent parameter.
      * @param event The complete event record for the typed key
      *
      * @return Return true if the event was handled here, or false if not.
      */
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        switch (keyCode) {
-        case KeyEvent.KEYCODE_BACK:
-            cancel();
+        if (DBG) Log.d(LOG_TAG, "onKeyDown(" + keyCode + "," + event + ")");
+        
+        // handle back key to go back to previous searchable, etc.
+        if (handleBackKey(keyCode, event)) {
             return true;
-        case KeyEvent.KEYCODE_SEARCH:
-            if (TextUtils.getTrimmedLength(mSearchTextField.getText()) != 0) {
-                launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
+        }
+        
+        // search or cancel on search key
+        if (keyCode == KeyEvent.KEYCODE_SEARCH) {
+            if (!mSearchAutoComplete.isEmpty()) {
+                launchQuerySearch();
             } else {
                 cancel();
             }
             return true;
-        default:
-            SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
-            if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) {
-                launchQuerySearch(keyCode, actionKey.mQueryActionMsg);
-                return true;
-            }
-            break;
         }
+
+        // if it's an action specified by the searchable activity, launch the
+        // entered query with the action key
+        SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
+        if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) {
+            launchQuerySearch(keyCode, actionKey.mQueryActionMsg);
+            return true;
+        }
+        
         return false;
     }
-
+    
     /**
      * Callback to watch the textedit field for empty/non-empty
      */
     private TextWatcher mTextWatcher = new TextWatcher() {
 
-        public void beforeTextChanged(CharSequence s, int start, int
-                before, int after) { }
+        public void beforeTextChanged(CharSequence s, int start, int before, int after) { }
 
         public void onTextChanged(CharSequence s, int start,
                 int before, int after) {
-            if (DBG_LOG_TIMING == 1) {
+            if (DBG_LOG_TIMING) {
                 dbgLogTiming("onTextChanged()");
             }
             updateWidgetState();
-            // Only do suggestions if actually typed by user
-            if ((mSuggestionsAdapter != null) && !mSuggestionsAdapter.getNonUserQuery()) {
-                mPreviousSuggestionQuery = s.toString();
-                mUserQuery = mSearchTextField.getText().toString();
-                mUserQuerySelStart = mSearchTextField.getSelectionStart();
-                mUserQuerySelEnd = mSearchTextField.getSelectionEnd();
+            if (!mSearchAutoComplete.isPerformingCompletion()) {
+                // The user changed the query, remember it.
+                mUserQuery = s == null ? "" : s.toString();
             }
         }
 
@@ -616,64 +736,34 @@
      */
     private void updateWidgetState() {
         // enable the button if we have one or more non-space characters
-        boolean enabled =
-            TextUtils.getTrimmedLength(mSearchTextField.getText()) != 0;
-
+        boolean enabled = !mSearchAutoComplete.isEmpty();
         mGoButton.setEnabled(enabled);
         mGoButton.setFocusable(enabled);
     }
 
-    private final static String[] ONE_LINE_FROM =       {SearchManager.SUGGEST_COLUMN_TEXT_1 };
-    private final static String[] ONE_LINE_ICONS_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1,
-                                                         SearchManager.SUGGEST_COLUMN_ICON_1,
-                                                         SearchManager.SUGGEST_COLUMN_ICON_2};
-    private final static String[] TWO_LINE_FROM =       {SearchManager.SUGGEST_COLUMN_TEXT_1,
-                                                         SearchManager.SUGGEST_COLUMN_TEXT_2 };
-    private final static String[] TWO_LINE_ICONS_FROM = {SearchManager.SUGGEST_COLUMN_TEXT_1,
-                                                         SearchManager.SUGGEST_COLUMN_TEXT_2,
-                                                         SearchManager.SUGGEST_COLUMN_ICON_1,
-                                                         SearchManager.SUGGEST_COLUMN_ICON_2 };
-    
-    private final static int[] ONE_LINE_TO =       {com.android.internal.R.id.text1};
-    private final static int[] ONE_LINE_ICONS_TO = {com.android.internal.R.id.text1,
-                                                    com.android.internal.R.id.icon1, 
-                                                    com.android.internal.R.id.icon2};
-    private final static int[] TWO_LINE_TO =       {com.android.internal.R.id.text1, 
-                                                    com.android.internal.R.id.text2};
-    private final static int[] TWO_LINE_ICONS_TO = {com.android.internal.R.id.text1, 
-                                                    com.android.internal.R.id.text2,
-                                                    com.android.internal.R.id.icon1, 
-                                                    com.android.internal.R.id.icon2};
-    
-    /**
-     * Safely retrieve the suggestions cursor adapter from the ListView
-     * 
-     * @param adapterView The ListView containing our adapter
-     * @result The CursorAdapter that we installed, or null if not set
-     */
-    private static CursorAdapter getSuggestionsAdapter(AdapterView<?> adapterView) {
-        CursorAdapter result = null;
-        if (adapterView != null) {
-            Object ad = adapterView.getAdapter();
-            if (ad instanceof CursorAdapter) {
-                result = (CursorAdapter) ad;
-            } else if (ad instanceof WrapperListAdapter) {
-                result = (CursorAdapter) ((WrapperListAdapter)ad).getWrappedAdapter();
-            }
-        }
-        return result;
-    }
-
     /**
      * React to typing in the GO search button by refocusing to EditText. 
      * Continue typing the query.
      */
     View.OnKeyListener mButtonsKeyListener = new View.OnKeyListener() {
         public boolean onKey(View v, int keyCode, KeyEvent event) {
-            // also guard against possible race conditions (late arrival after dismiss)
-            if (mSearchable != null) {
-                return refocusingKeyListener(v, keyCode, event);
+            // guard against possible race conditions
+            if (mSearchable == null) {
+                return false;
             }
+            
+            if (!event.isSystem() && 
+                    (keyCode != KeyEvent.KEYCODE_DPAD_UP) &&
+                    (keyCode != KeyEvent.KEYCODE_DPAD_DOWN) &&
+                    (keyCode != KeyEvent.KEYCODE_DPAD_LEFT) &&
+                    (keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) &&
+                    (keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) {
+                // restore focus and give key to EditText ...
+                if (mSearchAutoComplete.requestFocus()) {
+                    return mSearchAutoComplete.dispatchKeyEvent(event);
+                }
+            }
+
             return false;
         }
     };
@@ -683,10 +773,11 @@
      */
     View.OnClickListener mGoButtonClickListener = new View.OnClickListener() {
         public void onClick(View v) {
-            // also guard against possible race conditions (late arrival after dismiss)
-            if (mSearchable != null) {
-                launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
+            // guard against possible race conditions
+            if (mSearchable == null) {
+                return;
             }
+            launchQuerySearch();
         }
     };
     
@@ -695,14 +786,16 @@
      */
     View.OnClickListener mVoiceButtonClickListener = new View.OnClickListener() {
         public void onClick(View v) {
+            // guard against possible race conditions
+            if (mSearchable == null) {
+                return;
+            }
             try {
                 if (mSearchable.getVoiceSearchLaunchWebSearch()) {
                     getContext().startActivity(mVoiceWebSearchIntent);
-                    dismiss();
                 } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
                     Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent);
                     getContext().startActivity(appSearchIntent);
-                    dismiss();
                 }
             } catch (ActivityNotFoundException e) {
                 // Should not happen, since we check the availability of
@@ -778,136 +871,56 @@
      */
     View.OnKeyListener mTextKeyListener = new View.OnKeyListener() {
         public boolean onKey(View v, int keyCode, KeyEvent event) {
-            if (keyCode == KeyEvent.KEYCODE_BACK) {
-                cancel();
-                return true;
+            // guard against possible race conditions
+            if (mSearchable == null) {
+                return false;
             }
-            // also guard against possible race conditions (late arrival after dismiss)
-            if (mSearchable != null && 
-                    TextUtils.getTrimmedLength(mSearchTextField.getText()) > 0) {
-                if (DBG_LOG_TIMING == 1) {
-                    dbgLogTiming("doTextKey()");
+
+            if (DBG_LOG_TIMING) dbgLogTiming("doTextKey()");
+            if (DBG) { 
+                Log.d(LOG_TAG, "mTextListener.onKey(" + keyCode + "," + event 
+                        + "), selection: " + mSearchAutoComplete.getListSelection());
+            }
+            
+            // If a suggestion is selected, handle enter, search key, and action keys 
+            // as presses on the selected suggestion
+            if (mSearchAutoComplete.isPopupShowing() && 
+                    mSearchAutoComplete.getListSelection() != ListView.INVALID_POSITION) {
+                return onSuggestionsKey(v, keyCode, event);
+            }
+
+            // If there is text in the query box, handle enter, and action keys
+            // The search key is handled by the dialog's onKeyDown(). 
+            if (!mSearchAutoComplete.isEmpty()) {
+                if (keyCode == KeyEvent.KEYCODE_ENTER 
+                        && event.getAction() == KeyEvent.ACTION_UP) {
+                    v.cancelLongPress();
+                    launchQuerySearch();                    
+                    return true;
                 }
-                // dispatch "typing in the list" first
-                if (mSearchTextField.isPopupShowing() && 
-                        mSearchTextField.getListSelection() != ListView.INVALID_POSITION) {
-                     return onSuggestionsKey(v, keyCode, event);
-                }
-                // otherwise, dispatch an "edit view" key
-                switch (keyCode) {
-                case KeyEvent.KEYCODE_ENTER:
-                    if (event.getAction() == KeyEvent.ACTION_UP) {
-                        v.cancelLongPress();
-                        launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);                    
+                if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                    SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
+                    if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) {
+                        launchQuerySearch(keyCode, actionKey.mQueryActionMsg);
                         return true;
                     }
-                    break;
-                case KeyEvent.KEYCODE_DPAD_DOWN:                    
-                    // capture the EditText state, so we can restore the user entry later
-                    mUserQuery = mSearchTextField.getText().toString();
-                    mUserQuerySelStart = mSearchTextField.getSelectionStart();
-                    mUserQuerySelEnd = mSearchTextField.getSelectionEnd();
-                    // pass through - we're just watching here
-                    break;
-                default:
-                    if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                        SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
-                        if ((actionKey != null) && (actionKey.mQueryActionMsg != null)) {
-                            launchQuerySearch(keyCode, actionKey.mQueryActionMsg);
-                            return true;
-                        }
-                    }
-                    break;
                 }
             }
             return false;
         }
     };
-
+        
     /**
-     * React to the user typing while the suggestions are focused.  First, check for action
-     * keys.  If not handled, try refocusing regular characters into the EditText.  In this case,
-     * replace the query text (start typing fresh text).
-     */
-    private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) {
-        boolean handled = false;
-        // also guard against possible race conditions (late arrival after dismiss)
-        if (mSearchable != null) {
-            handled = doSuggestionsKey(v, keyCode, event);
-        }
-        return handled;
-    }
-    
-    /**
-     * Per UI design, we're going to "steer" any typed keystrokes back into the EditText
-     * box, even if the user has navigated the focus to the dropdown or to the GO button.
-     * 
-     * @param v The view into which the keystroke was typed
-     * @param keyCode keyCode of entered key
-     * @param event Full KeyEvent record of entered key
-     */
-    private boolean refocusingKeyListener(View v, int keyCode, KeyEvent event) {
-        boolean handled = false;
-
-        if (!event.isSystem() && 
-                (keyCode != KeyEvent.KEYCODE_DPAD_UP) &&
-                (keyCode != KeyEvent.KEYCODE_DPAD_DOWN) &&
-                (keyCode != KeyEvent.KEYCODE_DPAD_LEFT) &&
-                (keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) &&
-                (keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) {
-            // restore focus and give key to EditText ...
-            // but don't replace the user's query
-            mLeaveJammedQueryOnRefocus = true;
-            if (mSearchTextField.requestFocus()) {
-                handled = mSearchTextField.dispatchKeyEvent(event);
-            }
-            mLeaveJammedQueryOnRefocus = false;
-        }
-        return handled;
-    }
-    
-    /**
-     * Update query text based on transitions in and out of suggestions list.
-     */
-    /*
-     * TODO - figure out if this logic is required for the autocomplete text view version
-
-    OnFocusChangeListener mSuggestFocusListener = new OnFocusChangeListener() {
-        public void onFocusChange(View v, boolean hasFocus) {
-            // also guard against possible race conditions (late arrival after dismiss)
-            if (mSearchable == null) {
-                return;
-            }
-            // Update query text based on navigation in to/out of the suggestions list
-            if (hasFocus) {
-                // Entering the list view - record selection point from user's query
-                mUserQuery = mSearchTextField.getText().toString();
-                mUserQuerySelStart = mSearchTextField.getSelectionStart();
-                mUserQuerySelEnd = mSearchTextField.getSelectionEnd();
-                // then update the query to match the entered selection
-                jamSuggestionQuery(true, mSuggestionsList, 
-                                    mSuggestionsList.getSelectedItemPosition());
-            } else {
-                // Exiting the list view
-                
-                if (mSuggestionsList.getSelectedItemPosition() < 0) {
-                    // Direct exit - Leave new suggestion in place (do nothing)
-                } else {
-                    // Navigation exit - restore user's query text
-                    if (!mLeaveJammedQueryOnRefocus) {
-                        jamSuggestionQuery(false, null, -1);
-                    }
-                }
-            }
-
-        }
-    };
-    */
-    
-    /**
-     * This is the listener for the ACTION_CLOSE_SYSTEM_DIALOGS intent.  It's an indication that
-     * we should close ourselves immediately, in order to allow a higher-priority UI to take over
+     * When the ACTION_CLOSE_SYSTEM_DIALOGS intent is received, we should close ourselves 
+     * immediately, in order to allow a higher-priority UI to take over
      * (e.g. phone call received).
+     * 
+     * When a package is added, removed or changed, our current context
+     * may no longer be valid.  This would only happen if a package is installed/removed exactly
+     * when the search bar is open.  So for now we're just going to close the search
+     * bar.  
+     * Anything fancier would require some checks to see if the user's context was still valid.
+     * Which would be messier.
      */
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -918,7 +931,7 @@
             } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)
                     || Intent.ACTION_PACKAGE_REMOVED.equals(action)
                     || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
-                onPackageListChange();
+                cancel();
             }
         }
     };
@@ -938,58 +951,45 @@
     }
     
     /**
-     * Various ways to launch searches
+     * React to the user typing while in the suggestions list. First, check for action
+     * keys. If not handled, try refocusing regular characters into the EditText. 
      */
-
-    /**
-     * React to the user clicking the "GO" button.  Hide the UI and launch a search.
-     *
-     * @param actionKey Pass a keycode if the launch was triggered by an action key.  Pass
-     * KeyEvent.KEYCODE_UNKNOWN for no actionKey code.
-     * @param actionMsg Pass the suggestion-provided message if the launch was triggered by an
-     * action key.  Pass null for no actionKey message.
-     */
-    private void launchQuerySearch(int actionKey, final String actionMsg)  {
-        final String query = mSearchTextField.getText().toString();
-        final Bundle appData = mAppSearchData;
-        final SearchableInfo si = mSearchable;      // cache briefly (dismiss() nulls it)
-        dismiss();
-        sendLaunchIntent(Intent.ACTION_SEARCH, null, query, appData, actionKey, actionMsg, si);
-    }
-
-    /**
-     * React to the user typing an action key while in the suggestions list
-     */
-    private boolean doSuggestionsKey(View v, int keyCode, KeyEvent event) {
-        // Exit early in case of race condition
+    private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) {
+        // guard against possible race conditions (late arrival after dismiss)
+        if (mSearchable == null) {
+            return false;
+        }
         if (mSuggestionsAdapter == null) {
             return false;
         }
         if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            if (DBG_LOG_TIMING == 1) {
-                dbgLogTiming("doSuggestionsKey()");
+            if (DBG_LOG_TIMING) {
+                dbgLogTiming("onSuggestionsKey()");
             }
             
             // First, check for enter or search (both of which we'll treat as a "click")
             if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) {
-                int position = mSearchTextField.getListSelection();
-                return launchSuggestion(mSuggestionsAdapter, position);
+                int position = mSearchAutoComplete.getListSelection();
+                return launchSuggestion(position);
             }
             
             // Next, check for left/right moves, which we use to "return" the user to the edit view
             if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
-                // give "focus" to text editor, but don't restore the user's original query
+                // give "focus" to text editor, with cursor at the beginning if
+                // left key, at end if right key
+                // TODO: Reverse left/right for right-to-left languages, e.g. Arabic
                 int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 
-                        0 : mSearchTextField.length();
-                mSearchTextField.setSelection(selPoint);
-                mSearchTextField.setListSelection(0);
-                mSearchTextField.clearListSelection();
+                        0 : mSearchAutoComplete.length();
+                mSearchAutoComplete.setSelection(selPoint);
+                mSearchAutoComplete.setListSelection(0);
+                mSearchAutoComplete.clearListSelection();
                 return true;
             }
             
             // Next, check for an "up and out" move
-            if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mSearchTextField.getListSelection()) {
-                jamSuggestionQuery(false, null, -1);
+            if (keyCode == KeyEvent.KEYCODE_DPAD_UP 
+                    && 0 == mSearchAutoComplete.getListSelection()) {
+                restoreUserQuery();
                 // let ACTV complete the move
                 return false;
             }
@@ -999,222 +999,239 @@
             if ((actionKey != null) && 
                     ((actionKey.mSuggestActionMsg != null) || 
                      (actionKey.mSuggestActionMsgColumn != null))) {
-                //   launch suggestion using action key column
-                int position = mSearchTextField.getListSelection();
-                if (position >= 0) {
+                // launch suggestion using action key column
+                int position = mSearchAutoComplete.getListSelection();
+                if (position != ListView.INVALID_POSITION) {
                     Cursor c = mSuggestionsAdapter.getCursor();
                     if (c.moveToPosition(position)) {
                         final String actionMsg = getActionKeyMessage(c, actionKey);
                         if (actionMsg != null && (actionMsg.length() > 0)) {
-                            // shut down search bar and launch the activity
-                            // cache everything we need because dismiss releases mems
-                            setupSuggestionIntent(c, mSearchable);
-                            final String query = mSearchTextField.getText().toString();
-                            final Bundle appData =  mAppSearchData;
-                            SearchableInfo si = mSearchable;
-                            String suggestionAction = mSuggestionAction;
-                            Uri suggestionData = mSuggestionData;
-                            String suggestionQuery = mSuggestionQuery;
-                            dismiss();
-                            sendLaunchIntent(suggestionAction, suggestionData,
-                                    suggestionQuery, appData,
-                                             keyCode, actionMsg, si);
-                            return true;
+                            return launchSuggestion(position, keyCode, actionMsg);
                         }
                     }
                 }
             }
         }
         return false;
-    }    
-
+    }
+    
     /**
-     * Set or reset the user query to follow the selections in the suggestions
-     * 
-     * @param jamQuery True means to set the query, false means to reset it to the user's choice
+     * Launch a search for the text in the query text field.
      */
-    private void jamSuggestionQuery(boolean jamQuery, AdapterView<?> parent, int position) {
-        // quick check against race conditions
-        if (mSearchable == null) {
-            return;
-        }
-        
-        mSuggestionsAdapter.setNonUserQuery(true);       // disables any suggestions processing
-        if (jamQuery) {
-            CursorAdapter ca = getSuggestionsAdapter(parent);
-            Cursor c = ca.getCursor();
-            if (c.moveToPosition(position)) {
-                setupSuggestionIntent(c, mSearchable);
-                String jamText = null;
-
-                // Simple heuristic for selecting text with which to rewrite the query.
-                if (mSuggestionQuery != null) {
-                    jamText = mSuggestionQuery;
-                } else if (mSearchable.mQueryRewriteFromData && (mSuggestionData != null)) {
-                    jamText = mSuggestionData.toString();
-                } else if (mSearchable.mQueryRewriteFromText) {
-                    try {
-                        int column = c.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1);
-                        jamText = c.getString(column);
-                    } catch (RuntimeException e) {
-                        // no work here, jamText is null
-                    }
-                }
-                if (jamText != null) {
-                    mSearchTextField.setText(jamText);
-                    /* mSearchTextField.selectAll(); */ // this didn't work anyway in the old UI
-                    // TODO this is only needed in the model where we have a selection in the ACTV
-                    // and in the dropdown at the same time.
-                    mSearchTextField.setSelection(jamText.length());
-                }
-            }
-        } else {
-            // reset user query
-            mSearchTextField.setText(mUserQuery);
-            try {
-                mSearchTextField.setSelection(mUserQuerySelStart, mUserQuerySelEnd);
-            } catch (IndexOutOfBoundsException e) {
-                // In case of error, just select all
-                Log.e(LOG_TAG, "Caught IndexOutOfBoundsException while setting selection.  " +
-                        "start=" + mUserQuerySelStart + " end=" + mUserQuerySelEnd +
-                        " text=\"" + mUserQuery + "\"");
-                mSearchTextField.selectAll();
-            }
-        }
-        // TODO because the new query is (not) processed in another thread, we can't just
-        // take away this flag (yet).  The better solution here is going to require a new API
-        // in AutoCompleteTextView which allows us to change the text w/o changing the suggestions.
-//      mSuggestionsAdapter.setNonUserQuery(false);
+    protected void launchQuerySearch()  {
+        launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
     }
 
     /**
-     * Assemble a search intent and send it.
+     * Launch a search for the text in the query text field.
      *
-     * @param action The intent to send, typically Intent.ACTION_SEARCH
-     * @param data The data for the intent
-     * @param query The user text entered (so far)
-     * @param appData The app data bundle (if supplied)
-     * @param actionKey If the intent was triggered by an action key, e.g. KEYCODE_CALL, it will
-     * be sent here.  Pass KeyEvent.KEYCODE_UNKNOWN for no actionKey code.
-     * @param actionMsg If the intent was triggered by an action key, e.g. KEYCODE_CALL, the
-     * corresponding tag message will be sent here.  Pass null for no actionKey message.
-     * @param si Reference to the current SearchableInfo.  Passed here so it can be used even after
-     * we've called dismiss(), which attempts to null mSearchable.
+     * @param actionKey The key code of the action key that was pressed,
+     *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
+     * @param actionMsg The message for the action key that was pressed,
+     *        or <code>null</code> if none.
      */
-    private void sendLaunchIntent(final String action, final Uri data, final String query,
-            final Bundle appData, int actionKey, final String actionMsg, final SearchableInfo si) {
-        Intent launcher = new Intent(action);
-
-        if (query != null) {
-            launcher.putExtra(SearchManager.QUERY, query);
-        }
-
-        if (data != null) {
-            launcher.setData(data);
-        }
-
-        if (appData != null) {
-            launcher.putExtra(SearchManager.APP_DATA, appData);
-        }
-
-        // add launch info (action key, etc.)
-        if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
-            launcher.putExtra(SearchManager.ACTION_KEY, actionKey);
-            launcher.putExtra(SearchManager.ACTION_MSG, actionMsg);
-        }
-
-        // attempt to enforce security requirement (no 3rd-party intents)
-        launcher.setComponent(si.mSearchActivity);
-
-        getContext().startActivity(launcher);
+    protected void launchQuerySearch(int actionKey, String actionMsg)  {
+        String query = mSearchAutoComplete.getText().toString();
+        Intent intent = createIntent(Intent.ACTION_SEARCH, null, query, null, 
+                actionKey, actionMsg);
+        launchIntent(intent);
     }
-
+    
     /**
-     * Shared code for launching a query from a suggestion.
-     * @param ca The cursor adapter containing the suggestions
-     * @param position The suggestion we'll be launching from
-     * @return true if a successful launch, false if could not (e.g. bad position)
+     * Launches an intent based on a suggestion.
+     * 
+     * @param position The index of the suggestion to create the intent from.
+     * @return true if a successful launch, false if could not (e.g. bad position).
      */
-    private boolean launchSuggestion(CursorAdapter ca, int position) {
-        Cursor c = ca.getCursor();
+    protected boolean launchSuggestion(int position) {
+        return launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null);
+    }
+    
+    /**
+     * Launches an intent based on a suggestion.
+     * 
+     * @param position The index of the suggestion to create the intent from.
+     * @param actionKey The key code of the action key that was pressed,
+     *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
+     * @param actionMsg The message for the action key that was pressed,
+     *        or <code>null</code> if none.
+     * @return true if a successful launch, false if could not (e.g. bad position).
+     */
+    protected boolean launchSuggestion(int position, int actionKey, String actionMsg) {
+        Cursor c = mSuggestionsAdapter.getCursor();
         if ((c != null) && c.moveToPosition(position)) {
-            setupSuggestionIntent(c, mSearchable);
-            
-            final Bundle appData =  mAppSearchData;
-            SearchableInfo si = mSearchable;
-            String suggestionAction = mSuggestionAction;
-            Uri suggestionData = mSuggestionData;
-            String suggestionQuery = mSuggestionQuery;
-            dismiss();
-            sendLaunchIntent(suggestionAction, suggestionData, suggestionQuery, appData,
-                                KeyEvent.KEYCODE_UNKNOWN, null, si);
+            Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg);
+            launchIntent(intent);
             return true;
         }
         return false;
     }
     
     /**
+     * Launches an intent. Also dismisses the search dialog if not in global search mode.
+     */
+    private void launchIntent(Intent intent) {
+        if (intent == null) {
+            return;
+        }
+        if (handleSpecialIntent(intent)){
+            return;
+        }
+        if (!mGlobalSearchMode) {
+            dismiss();
+        }
+        getContext().startActivity(intent);
+    }
+    
+    /**
+     * Handles the special intent actions declared in {@link SearchManager}.
+     * 
+     * @return <code>true</code> if the intent was handled.
+     */
+    private boolean handleSpecialIntent(Intent intent) {
+        String action = intent.getAction();
+        if (SearchManager.INTENT_ACTION_CHANGE_SEARCH_SOURCE.equals(action)) {
+            handleChangeSourceIntent(intent);
+            return true;
+        } else if (SearchManager.INTENT_ACTION_CURSOR_RESPOND.equals(action)) {
+            handleCursorRespondIntent(intent);
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Handles SearchManager#INTENT_ACTION_CHANGE_SOURCE.
+     */
+    private void handleChangeSourceIntent(Intent intent) {
+        Uri dataUri = intent.getData();
+        if (dataUri == null) {
+            Log.w(LOG_TAG, "SearchManager.INTENT_ACTION_CHANGE_SOURCE without intent data.");
+            return;
+        }
+        ComponentName componentName = ComponentName.unflattenFromString(dataUri.toString());
+        if (componentName == null) {
+            Log.w(LOG_TAG, "Invalid ComponentName: " + dataUri);
+            return;
+        }
+        if (DBG) Log.d(LOG_TAG, "Switching to " + componentName);
+        
+        ComponentName previous = mLaunchComponent;
+        if (!show(componentName, mAppSearchData, false)) {
+            Log.w(LOG_TAG, "Failed to switch to source " + componentName);
+            return;
+        }
+        pushPreviousComponent(previous);
+
+        String query = intent.getStringExtra(SearchManager.QUERY);
+        setUserQuery(query);
+    }
+    
+    /**
+     * Handles {@link SearchManager#INTENT_ACTION_CURSOR_RESPOND}.
+     */
+    private void handleCursorRespondIntent(Intent intent) {
+        Cursor c = mSuggestionsAdapter.getCursor();
+        if (c != null) {
+            c.respond(intent.getExtras());
+        }
+    }
+    
+    /**
+     * Saves the previous component that was searched, so that we can go
+     * back to it.
+     */
+    private void pushPreviousComponent(ComponentName componentName) {
+        if (mPreviousComponents == null) {
+            mPreviousComponents = new ArrayList<ComponentName>();
+        }
+        mPreviousComponents.add(componentName);
+    }
+    
+    /**
+     * Pops the previous component off the stack and returns it.
+     * 
+     * @return The component name, or <code>null</code> if there was
+     *         no previous component.
+     */
+    private ComponentName popPreviousComponent() {
+        if (mPreviousComponents == null) {
+            return null;
+        }
+        int size = mPreviousComponents.size();
+        if (size == 0) {
+            return null;
+        }
+        return mPreviousComponents.remove(size - 1);
+    }
+    
+    /**
+     * Goes back to the previous component that was searched, if any.
+     * 
+     * @return <code>true</code> if there was a previous component that we could go back to.
+     */
+    private boolean backToPreviousComponent() {
+        ComponentName previous = popPreviousComponent();
+        if (previous == null) {
+            return false;
+        }
+        if (!show(previous, mAppSearchData, false)) {
+            Log.w(LOG_TAG, "Failed to switch to source " + previous);
+            return false;
+        }
+        
+        // must touch text to trigger suggestions
+        // TODO: should this be the text as it was when the user left
+        // the source that we are now going back to?
+        String query = mSearchAutoComplete.getText().toString();
+        setUserQuery(query);
+        
+        return true;
+    }
+    
+    /**
      * When a particular suggestion has been selected, perform the various lookups required
      * to use the suggestion.  This includes checking the cursor for suggestion-specific data,
      * and/or falling back to the XML for defaults;  It also creates REST style Uri data when
      * the suggestion includes a data id.
      * 
-     * NOTE:  Return values are in member variables mSuggestionAction & mSuggestionData.
-     * 
      * @param c The suggestions cursor, moved to the row of the user's selection
-     * @param si The searchable activity's info record
+     * @param actionKey The key code of the action key that was pressed,
+     *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
+     * @param actionMsg The message for the action key that was pressed,
+     *        or <code>null</code> if none.
+     * @return An intent for the suggestion at the cursor's position.
      */
-    void setupSuggestionIntent(Cursor c, SearchableInfo si) {
+    private Intent createIntentFromSuggestion(Cursor c, int actionKey, String actionMsg) {
         try {
             // use specific action if supplied, or default action if supplied, or fixed default
-            mSuggestionAction = null;
-            int mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_ACTION);
-            if (mColumn >= 0) {
-                final String action = c.getString(mColumn);
-                if (action != null) {
-                    mSuggestionAction = action;
-                }
+            String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION);
+            if (action == null) {
+                action = mSearchable.getSuggestIntentAction();
             }
-            if (mSuggestionAction == null) {
-                mSuggestionAction = si.getSuggestIntentAction();
-            }
-            if (mSuggestionAction == null) {
-                mSuggestionAction = Intent.ACTION_SEARCH;
+            if (action == null) {
+                action = Intent.ACTION_SEARCH;
             }
             
             // use specific data if supplied, or default data if supplied
-            String data = null;
-            mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA);
-            if (mColumn >= 0) {
-                final String rowData = c.getString(mColumn);
-                if (rowData != null) {
-                    data = rowData;
-                }
-            }
+            String data = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA);
             if (data == null) {
-                data = si.getSuggestIntentData();
+                data = mSearchable.getSuggestIntentData();
             }
-            
             // then, if an ID was provided, append it.
             if (data != null) {
-                mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
-                if (mColumn >= 0) {
-                    final String id = c.getString(mColumn);
-                    if (id != null) {
-                        data = data + "/" + Uri.encode(id);
-                    }
+                String id = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
+                if (id != null) {
+                    data = data + "/" + Uri.encode(id);
                 }
             }
-            mSuggestionData = (data == null) ? null : Uri.parse(data);
+            Uri dataUri = (data == null) ? null : Uri.parse(data);
+
+            String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
             
-            mSuggestionQuery = null;
-            mColumn = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY);
-            if (mColumn >= 0) {
-                final String query = c.getString(mColumn);
-                if (query != null) {
-                    mSuggestionQuery = query;
-                }
-            }
+            String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY);
+
+            return createIntent(action, dataUri, query, extraData, actionKey, actionMsg);
         } catch (RuntimeException e ) {
             int rowNum;
             try {                       // be really paranoid now
@@ -1224,10 +1241,49 @@
             }
             Log.w(LOG_TAG, "Search Suggestions cursor at row " + rowNum + 
                             " returned exception" + e.toString());
+            return null;
         }
     }
     
     /**
+     * Constructs an intent from the given information and the search dialog state.
+     * 
+     * @param action Intent action.
+     * @param data Intent data, or <code>null</code>.
+     * @param query Intent query, or <code>null</code>.
+     * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>.
+     * @param actionKey The key code of the action key that was pressed,
+     *        or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
+     * @param actionMsg The message for the action key that was pressed,
+     *        or <code>null</code> if none.
+     * @return The intent.
+     */
+    private Intent createIntent(String action, Uri data, String query, String extraData,
+            int actionKey, String actionMsg) {
+        // Now build the Intent
+        Intent intent = new Intent(action);
+        if (data != null) {
+            intent.setData(data);
+        }
+        if (query != null) {
+            intent.putExtra(SearchManager.QUERY, query);
+        }
+        if (extraData != null) {
+            intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
+        }
+        if (mAppSearchData != null) {
+            intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
+        }
+        if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
+            intent.putExtra(SearchManager.ACTION_KEY, actionKey);
+            intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
+        }
+        // attempt to enforce security requirement (no 3rd-party intents)
+        intent.setComponent(mSearchable.mSearchActivity);
+        return intent;
+    }
+    
+    /**
      * For a given suggestion and a given cursor row, get the action message.  If not provided
      * by the specific row/column, also check for a single definition (for the action key).
      * 
@@ -1236,17 +1292,12 @@
      * 
      * @return Returns a string, or null if no action key message for this suggestion
      */
-    private String getActionKeyMessage(Cursor c, final SearchableInfo.ActionKeyInfo actionKey) {
+    private static String getActionKeyMessage(Cursor c, SearchableInfo.ActionKeyInfo actionKey) {
         String result = null;
         // check first in the cursor data, for a suggestion-specific message
         final String column = actionKey.mSuggestActionMsgColumn;
         if (column != null) {
-            try {
-                int colId = c.getColumnIndexOrThrow(column);
-                result = c.getString(colId);
-            } catch (RuntimeException e) {
-                // OK - result is already null
-            }
+            result = SuggestionsAdapter.getColumnString(c, column);
         }
         // If the cursor didn't give us a message, see if there's a single message defined
         // for the actionkey (for all suggestions)
@@ -1257,343 +1308,179 @@
     }
         
     /**
-     * Local subclass for AutoCompleteTextView
-     * 
-     * This exists entirely to override the threshold method.  Otherwise we just use the class
-     * as-is.
+     * Local subclass for AutoCompleteTextView.
      */
     public static class SearchAutoComplete extends AutoCompleteTextView {
 
+        private int mThreshold;
+        private SearchDialog mSearchDialog;
+        
         public SearchAutoComplete(Context context) {
             super(null);
+            mThreshold = getThreshold();
         }
         
         public SearchAutoComplete(Context context, AttributeSet attrs) {
             super(context, attrs);
+            mThreshold = getThreshold();
         }
 
         public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) {
             super(context, attrs, defStyle);
+            mThreshold = getThreshold();
+        }
+
+        private void setSearchDialog(SearchDialog searchDialog) {
+            mSearchDialog = searchDialog;
+        }
+        
+        @Override
+        public void setThreshold(int threshold) {
+            super.setThreshold(threshold);
+            mThreshold = threshold;
+        }
+
+        /**
+         * Returns true if the text field is empty, or contains only whitespace.
+         */
+        private boolean isEmpty() {
+            return TextUtils.getTrimmedLength(getText()) == 0;
         }
         
         /**
-         * We never allow ACTV to automatically replace the text, since we use "jamSuggestionQuery"
-         * to do that.  There's no point in letting ACTV do this here, because in the search UI,
-         * as soon as we click a suggestion, we're going to start shutting things down.
+         * Clears the entered text.
+         */
+        private void clear() {
+            setText("");
+        }
+        
+        /**
+         * We override this method to avoid replacing the query box text
+         * when a suggestion is clicked.
          */
         @Override
-        public void replaceText(CharSequence text) {
+        protected void replaceText(CharSequence text) {
         }
         
         /**
-         * We always return true, so that the effective threshold is "zero".  This allows us
-         * to provide "null" suggestions such as "just show me some recent entries".
+         * We override this method so that we can allow a threshold of zero, which ACTV does not.
          */
         @Override
         public boolean enoughToFilter() {
-            return true;
+            return mThreshold <= 0 || super.enoughToFilter();
+        }
+
+        /**
+         * {@link AutoCompleteTextView#onKeyPreIme(int, KeyEvent)}) dismisses the drop-down on BACK,
+         * so we must override this method to modify the BACK behavior.
+         */
+        @Override
+        public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
+                if (mSearchDialog.backToPreviousComponent()) {
+                    return true;
+                }
+                return false; // will dismiss soft keyboard if necessary
+            }
+            return false;
         }
     }
     
-    /**
-     * Support for AutoCompleteTextView-based suggestions
-     */
-    /**
-     * This class provides the filtering-based interface to suggestions providers.
-     * It is hardwired in a couple of places to support GoogleSearch - for example, it supports
-     * two-line suggestions, but it does not support icons.
-     */
-    private static class SuggestionsAdapter extends SimpleCursorAdapter {
-        private final String TAG = "SuggestionsAdapter";
-        
-        SearchableInfo mSearchable;
-        private Resources mProviderResources;
-        
-        // These private variables are shared by the filter thread and must be protected
-        private WeakReference<Cursor> mRecentCursor = new WeakReference<Cursor>(null);
-        private boolean mNonUserQuery = false;
-        private AutoCompleteTextView mParentView;
-
-        public SuggestionsAdapter(Context context, SearchableInfo searchable,
-                AutoCompleteTextView actv) {
-            super(context, -1, null, null, null);
-            mSearchable = searchable;
-            mParentView = actv;
-            
-            // set up provider resources (gives us icons, etc.)
-            Context activityContext = mSearchable.getActivityContext(mContext);
-            Context providerContext = mSearchable.getProviderContext(mContext, activityContext);
-            mProviderResources = providerContext.getResources();
+    protected boolean handleBackKey(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
+            if (backToPreviousComponent()) {
+                return true;
+            }
+            cancel();
+            return true;
         }
-        
-        /**
-         * Set this field (temporarily!) to disable suggestions updating.  This allows us
-         * to change the string in the text view without changing the suggestions list.
-         */
-        public void setNonUserQuery(boolean nonUserQuery) {
-            synchronized (this) {
-                mNonUserQuery = nonUserQuery;
-            }
-        }
-        
-        public boolean getNonUserQuery() {
-            synchronized (this) {
-                return mNonUserQuery;
-            }
-        }
-
-        /**
-         * Use the search suggestions provider to obtain a live cursor.  This will be called
-         * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions).
-         * The results will be processed in the UI thread and changeCursor() will be called.
-         * 
-         * In order to provide the Search Mgr functionality of seeing your query change as you
-         * scroll through the list, we have to be able to jam new text into the string without
-         * retriggering the suggestions.  We do that here via the "nonUserQuery" flag.  In that
-         * case we simply return the existing cursor.
-         * 
-         * TODO: Dianne suggests that this should simply be promoted into an AutoCompleteTextView
-         * behavior (perhaps optionally).
-         * 
-         * TODO: The "nonuserquery" logic has a race condition because it happens in another thread.
-         * This also needs to be fixed.
-         */
-        @Override
-        public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
-            String query = (constraint == null) ? "" : constraint.toString();
-            Cursor c = null;
-            synchronized (this) {
-                if (mNonUserQuery) {
-                    c = mRecentCursor.get();
-                    mNonUserQuery = false;
-                }
-            }
-            if (c == null) {
-                c = getSuggestions(mSearchable, query);
-                synchronized (this) {
-                    mRecentCursor = new WeakReference<Cursor>(c);
-                }
-            }
-            return c;
-        }
-        
-        /**
-         * Overriding changeCursor() allows us to change not only the cursor, but by sampling
-         * the cursor's columns, the actual display characteristics of the list.
-         */
-        @Override
-        public void changeCursor(Cursor c) {
-            
-            // first, check for various conditions that disqualify this cursor
-            if ((c == null) || (c.getCount() == 0)) {
-                // no cursor, or cursor with no data
-                changeCursorAndColumns(null, null, null);
-                if (c != null) {
-                    c.close();
-                }
-                return;
-            }
-
-            // check cursor before trying to create list views from it
-            int colId = c.getColumnIndex("_id");
-            int col1 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
-            int col2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
-            int colIc1 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
-            int colIc2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
-
-            boolean minimal = (colId >= 0) && (col1 >= 0);
-            boolean hasIcons = (colIc1 >= 0) && (colIc2 >= 0);
-            boolean has2Lines = col2 >= 0;
-
-            if (minimal) {
-                int layout;
-                String[] from;
-                int[] to;
-
-                if (hasIcons) {
-                    if (has2Lines) {
-                        layout = com.android.internal.R.layout.search_dropdown_item_icons_2line;
-                        from = TWO_LINE_ICONS_FROM;
-                        to = TWO_LINE_ICONS_TO;
-                    } else {
-                        layout = com.android.internal.R.layout.search_dropdown_item_icons_1line;
-                        from = ONE_LINE_ICONS_FROM;
-                        to = ONE_LINE_ICONS_TO;
-                    }
-                } else {
-                    if (has2Lines) {
-                        layout = com.android.internal.R.layout.search_dropdown_item_2line;
-                        from = TWO_LINE_FROM;
-                        to = TWO_LINE_TO;
-                    } else {
-                        layout = com.android.internal.R.layout.search_dropdown_item_1line;
-                        from = ONE_LINE_FROM;
-                        to = ONE_LINE_TO;
-                    }
-                }
-                // Force the underlying ListView to discard and reload all layouts
-                // (Note, this should be optimized for cases where layout/cursor remain same)
-                mParentView.resetListAndClearViews();
-                // Now actually set up the cursor, columns, and the list view
-                changeCursorAndColumns(c, from, to);
-                setViewResource(layout);          
-            } else {
-                // Provide some help for developers instead of just silently discarding
-                Log.w(LOG_TAG, "Suggestions cursor discarded due to missing required columns.");
-                changeCursorAndColumns(null, null, null);
-                c.close();
-            }
-            if ((colIc1 >= 0) != (colIc2 >= 0)) {
-                Log.w(LOG_TAG, "Suggestion icon column(s) discarded, must be 0 or 2 columns.");
-            }    
-        }
-        
-        /**
-         * Overriding this allows us to write the selected query back into the box.
-         * NOTE:  This is a vastly simplified version of SearchDialog.jamQuery() and does
-         * not universally support the search API.  But it is sufficient for Google Search.
-         */
-        @Override
-        public CharSequence convertToString(Cursor cursor) {
-            CharSequence result = null;
-            if (cursor != null) {
-                int column = cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY);
-                if (column >= 0) {
-                    final String query = cursor.getString(column);
-                    if (query != null) {
-                        result = query;
-                    }
-                }
-            }
-            return result;
-        }
-
-        /**
-         * Get the query cursor for the search suggestions.
-         * 
-         * TODO this is functionally identical to the version in SearchDialog.java.  Perhaps it 
-         * could be hoisted into SearchableInfo or some other shared spot.
-         * 
-         * @param query The search text entered (so far)
-         * @return Returns a cursor with suggestions, or null if no suggestions 
-         */
-        private Cursor getSuggestions(final SearchableInfo searchable, final String query) {
-            Cursor cursor = null;
-            if (searchable.getSuggestAuthority() != null) {
-                try {
-                    StringBuilder uriStr = new StringBuilder("content://");
-                    uriStr.append(searchable.getSuggestAuthority());
-
-                    // if content path provided, insert it now
-                    final String contentPath = searchable.getSuggestPath();
-                    if (contentPath != null) {
-                        uriStr.append('/');
-                        uriStr.append(contentPath);
-                    }
-
-                    // append standard suggestion query path 
-                    uriStr.append('/' + SearchManager.SUGGEST_URI_PATH_QUERY);
-
-                    // inject query, either as selection args or inline
-                    String[] selArgs = null;
-                    if (searchable.getSuggestSelection() != null) {    // use selection if provided
-                        selArgs = new String[] {query};
-                    } else {
-                        uriStr.append('/');                             // no sel, use REST pattern
-                        uriStr.append(Uri.encode(query));
-                    }
-
-                    // finally, make the query
-                    cursor = mContext.getContentResolver().query(
-                                                        Uri.parse(uriStr.toString()), null, 
-                                                        searchable.getSuggestSelection(), selArgs,
-                                                        null);
-                } catch (RuntimeException e) {
-                    Log.w(TAG, "Search Suggestions query returned exception " + e.toString());
-                    cursor = null;
-                }
-            }
-            
-            return cursor;
-        }
-
-        /**
-         * Overriding this allows us to affect the way that an icon is loaded.  Specifically,
-         * we can be more controlling about the resource path (and allow icons to come from other
-         * packages).
-         * 
-         * TODO: This is 100% identical to the version in SearchDialog.java
-         *
-         * @param v ImageView to receive an image
-         * @param value the value retrieved from the cursor
-         */
-        @Override
-        public void setViewImage(ImageView v, String value) {
-            int resID;
-            Drawable img = null;
-
-            try {
-                resID = Integer.parseInt(value);
-                if (resID != 0) {
-                    img = mProviderResources.getDrawable(resID);
-                }
-            } catch (NumberFormatException nfe) {
-                // img = null;
-            } catch (NotFoundException e2) {
-                // img = null;
-            }
-            
-            // finally, set the image to whatever we've gotten
-            v.setImageDrawable(img);
-        }
-        
-        /**
-         * This method is overridden purely to provide a bit of protection against
-         * flaky content providers.
-         * 
-         * TODO: This is 100% identical to the version in SearchDialog.java
-         * 
-         * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
-         */
-        @Override 
-        public View getView(int position, View convertView, ViewGroup parent) {
-            try {
-                return super.getView(position, convertView, parent);
-            } catch (RuntimeException e) {
-                Log.w(TAG, "Search Suggestions cursor returned exception " + e.toString());
-                // what can I return here?
-                View v = newView(mContext, mCursor, parent);
-                if (v != null) {
-                    TextView tv = (TextView) v.findViewById(com.android.internal.R.id.text1);
-                    tv.setText(e.toString());
-                }
-                return v;
-            }
-        }
-
+        return false;
     }
     
     /**
      * Implements OnItemClickListener
      */
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        // Log.d(LOG_TAG, "onItemClick() position " + position);
-        launchSuggestion(mSuggestionsAdapter, position);
+        if (DBG) Log.d(LOG_TAG, "onItemClick() position " + position);
+        launchSuggestion(position);
     }
-    
+
     /** 
      * Implements OnItemSelectedListener
      */
      public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-         // Log.d(LOG_TAG, "onItemSelected() position " + position);
-         jamSuggestionQuery(true, parent, position);
+         if (DBG) Log.d(LOG_TAG, "onItemSelected() position " + position);
+         // A suggestion has been selected, rewrite the query if possible,
+         // otherwise the restore the original query.
+         if (REWRITE_QUERIES) {
+             rewriteQueryFromSuggestion(position);
+         }
      }
 
      /** 
       * Implements OnItemSelectedListener
       */
      public void onNothingSelected(AdapterView<?> parent) {
-         // Log.d(LOG_TAG, "onNothingSelected()");
+         if (DBG) Log.d(LOG_TAG, "onNothingSelected()");
+     }
+     
+     /**
+      * Query rewriting.
+      */
+
+     private void rewriteQueryFromSuggestion(int position) {
+         Cursor c = mSuggestionsAdapter.getCursor();
+         if (c == null) {
+             return;
+         }
+         if (c.moveToPosition(position)) {
+             // Get the new query from the suggestion.
+             CharSequence newQuery = mSuggestionsAdapter.convertToString(c);
+             if (newQuery != null) {
+                 // The suggestion rewrites the query.
+                 if (DBG) Log.d(LOG_TAG, "Rewriting query to '" + newQuery + "'");
+                 // Update the text field, without getting new suggestions.
+                 setQuery(newQuery);
+             } else {
+                 // The suggestion does not rewrite the query, restore the user's query.
+                 if (DBG) Log.d(LOG_TAG, "Suggestion gives no rewrite, restoring user query.");
+                 restoreUserQuery();
+             }
+         } else {
+             // We got a bad position, restore the user's query.
+             Log.w(LOG_TAG, "Bad suggestion position: " + position);
+             restoreUserQuery();
+         }
+     }
+     
+     /** 
+      * Restores the query entered by the user if needed.
+      */
+     private void restoreUserQuery() {
+         if (DBG) Log.d(LOG_TAG, "Restoring query to '" + mUserQuery + "'");
+         setQuery(mUserQuery);
+     }
+     
+     /**
+      * Sets the text in the query box, without updating the suggestions.
+      */
+     private void setQuery(CharSequence query) {
+         mSearchAutoComplete.setText(query, false);
+         if (query != null) {
+             mSearchAutoComplete.setSelection(query.length());
+         }
+     }
+     
+     /**
+      * Sets the text in the query box, updating the suggestions.
+      */
+     private void setUserQuery(String query) {
+         if (query == null) {
+             query = "";
+         }
+         mUserQuery = query;
+         mSearchAutoComplete.setText(query);
+         mSearchAutoComplete.setSelection(query.length());
      }
 
     /**
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index ecdd3f8..3e9f3dd 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -17,12 +17,17 @@
 package android.app;
 
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Configuration;
+import android.database.Cursor;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.server.search.SearchableInfo;
 import android.view.KeyEvent;
 
 /**
@@ -439,20 +444,18 @@
  *     
  *     <tr><th>{@link #SUGGEST_COLUMN_ICON_1}</th>
  *         <td>If your cursor includes this column, then all suggestions will be provided in an
- *             icons+text format.  This value should be a reference (resource ID) of the icon to
+ *             icons+text format.  This value should be a reference to the icon to
  *             draw on the left side, or it can be null or zero to indicate no icon in this row.
- *             You must provide both cursor columns, or neither.
  *             </td>
- *         <td align="center">No, but required if you also have {@link #SUGGEST_COLUMN_ICON_2}</td>
+ *         <td align="center">No.</td>
  *     </tr>
  *     
  *     <tr><th>{@link #SUGGEST_COLUMN_ICON_2}</th>
  *         <td>If your cursor includes this column, then all suggestions will be provided in an
- *             icons+text format.  This value should be a reference (resource ID) of the icon to
+ *             icons+text format.  This value should be a reference to the icon to
  *             draw on the right side, or it can be null or zero to indicate no icon in this row.
- *             You must provide both cursor columns, or neither.
  *             </td>
- *         <td align="center">No, but required if you also have {@link #SUGGEST_COLUMN_ICON_1}</td>
+ *         <td align="center">No.</td>
  *     </tr>
  *     
  *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_ACTION}</th>
@@ -1155,6 +1158,13 @@
     public final static String ACTION_KEY = "action_key";
     
     /**
+     * Intent extra data key: This key will be used for the extra populated by the
+     * {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column.
+     * {@hide}
+     */
+    public final static String EXTRA_DATA_KEY = "intent_extra_data_key";
+    
+    /**
      * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
      * {@link android.content.Intent#getStringExtra content.Intent.getStringExtra()}
      * to obtain the action message that was defined for a particular search action key and/or
@@ -1195,21 +1205,59 @@
     public final static String SUGGEST_COLUMN_TEXT_2 = "suggest_text_2";
     /**
      * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
-     *  then all suggestions will be provided in format that includes space for two small icons,
+     *  then all suggestions will be provided in a format that includes space for two small icons,
      *  one at the left and one at the right of each suggestion.  The data in the column must
-     *  be a a resource ID for the icon you wish to have displayed.  If you include this column,
-     *  you must also include {@link #SUGGEST_COLUMN_ICON_2}.
+     *  be a resource ID of a drawable, or a URI in one of the following formats:
+     *
+     * <ul>
+     * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+     * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li>
+     * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+     * </ul>
+     *
+     * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)} 
+     * for more information on these schemes. 
      */
     public final static String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1";
     /**
      * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
-     *  then all suggestions will be provided in format that includes space for two small icons,
+     *  then all suggestions will be provided in a format that includes space for two small icons,
      *  one at the left and one at the right of each suggestion.  The data in the column must
-     *  be a a resource ID for the icon you wish to have displayed.  If you include this column,
-     *  you must also include {@link #SUGGEST_COLUMN_ICON_1}.
+     *  be a resource ID of a drawable, or a URI in one of the following formats:
+     *
+     * <ul>
+     * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+     * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li>
+     * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+     * </ul>
+     *
+     * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)} 
+     * for more information on these schemes. 
      */
     public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2";
     /**
+     * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
+     *  then all suggestions will be provided in a format that includes space for two small icons,
+     *  one at the left and one at the right of each suggestion.  The data in the column must
+     *  be a blob that contains a bitmap.
+     * 
+     * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_1} column.
+     *
+     * @hide
+     */
+    public final static String SUGGEST_COLUMN_ICON_1_BITMAP = "suggest_icon_1_bitmap";
+    /**
+     * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
+     *  then all suggestions will be provided in a format that includes space for two small icons,
+     *  one at the left and one at the right of each suggestion.  The data in the column must
+     *  be a blob that contains a bitmap.
+     * 
+     * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_2} column.
+     *
+     * @hide
+     */
+    public final static String SUGGEST_COLUMN_ICON_2_BITMAP = "suggest_icon_2_bitmap";
+    /**
      * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
      * this element exists at the given row, this is the action that will be used when
      * forming the suggestion's intent.  If the element is not provided, the action will be taken
@@ -1230,6 +1278,14 @@
      */
     public final static String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data";
     /**
+     * Column name for suggestions cursor.  <i>Optional.</i>  This column allows suggestions
+     *  to provide additional arbitrary data which will be included as an extra under the key
+     *  {@link #EXTRA_DATA_KEY}.
+     * 
+     * @hide pending API council approval
+     */
+    public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data";
+    /**
      * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
      * this element exists at the given row, then "/" and this value will be appended to the data
      * field in the Intent.  This should only be used if the data field has already been set to an
@@ -1244,6 +1300,54 @@
      */
     public final static String SUGGEST_COLUMN_QUERY = "suggest_intent_query";
 
+    /**
+     * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
+     * the search dialog will switch to a different suggestion source when the
+     * suggestion is clicked. 
+     * 
+     * {@link #SUGGEST_COLUMN_INTENT_DATA} must contain
+     * the flattened {@link ComponentName} of the activity which is to be searched.
+     * 
+     * TODO: Should {@link #SUGGEST_COLUMN_INTENT_DATA} instead contain a URI in the format
+     * used by {@link android.provider.Applications}?
+     * 
+     * TODO: This intent should be protected by the same permission that we use
+     * for replacing the global search provider.
+     * 
+     * The query text field will be set to the value of {@link #SUGGEST_COLUMN_QUERY}.
+     * 
+     * @hide Pending API council approval.
+     */
+    public final static String INTENT_ACTION_CHANGE_SEARCH_SOURCE 
+            = "android.search.action.CHANGE_SEARCH_SOURCE";
+    
+    /**
+     * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
+     * the search dialog will call {@link Cursor#respond(Bundle)} when the
+     * suggestion is clicked. 
+     * 
+     * The {@link Bundle} argument will be constructed
+     * in the same way as the "extra" bundle included in an Intent constructed 
+     * from the suggestion.
+     * 
+     * @hide Pending API council approval.
+     */
+    public final static String INTENT_ACTION_CURSOR_RESPOND
+            = "android.search.action.CURSOR_RESPOND";
+    
+    /**
+     * Intent action for starting the global search settings activity.
+     * The global search provider should handle this intent.
+     * 
+     * @hide Pending API council approval.
+     */
+    public final static String INTENT_ACTION_SEARCH_SETTINGS 
+            = "android.search.action.SEARCH_SETTINGS";
+    
+    /**
+     * Reference to the shared system search service.
+     */
+    private static ISearchManager sService = getSearchManagerService();
 
     private final Context mContext;
     private final Handler mHandler;
@@ -1257,12 +1361,6 @@
         mContext = context;
         mHandler = handler;
     }
-    private static ISearchManager mService;
-
-    static {
-        mService = ISearchManager.Stub.asInterface(
-                    ServiceManager.getService(Context.SEARCH_SERVICE));
-    }
     
     /**
      * Launch search UI.
@@ -1459,5 +1557,93 @@
             mSearchDialog.onConfigurationChanged(newConfig);
         }
     }
-      
+    
+    private static ISearchManager getSearchManagerService() {
+        return ISearchManager.Stub.asInterface(
+            ServiceManager.getService(Context.SEARCH_SERVICE));
+    }
+    
+    /**
+     * Gets information about a searchable activity. This method is static so that it can
+     * be used from non-Activity contexts.
+     *
+     * @param componentName The activity to get searchable information for.
+     * @param globalSearch If <code>false</code>, return information about the given activity.
+     *        If <code>true</code>, return information about the global search activity. 
+     * @return Searchable information, or <code>null</code> if the activity is not searchable.
+     * 
+     * @hide because SearchableInfo is not part of the API.
+     */
+    public static SearchableInfo getSearchableInfo(ComponentName componentName, 
+            boolean globalSearch) {
+        try {
+            return sService.getSearchableInfo(componentName, globalSearch);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+    
+    /**
+     * Checks whether the given searchable is the default searchable.
+     * 
+     * @hide because SearchableInfo is not part of the API.
+     */
+    public static boolean isDefaultSearchable(SearchableInfo searchable) {
+        SearchableInfo defaultSearchable = SearchManager.getSearchableInfo(null, true);
+        return defaultSearchable != null 
+                && defaultSearchable.mSearchActivity.equals(searchable.mSearchActivity);
+    }
+    
+    /**
+     * Gets a cursor with search suggestions. This method is static so that it can
+     * be used from non-Activity context.
+     *
+     * @param searchable Information about how to get the suggestions.
+     * @param query The search text entered (so far).
+     * @return a cursor with suggestions, or <code>null</null> the suggestion query failed. 
+     * 
+     * @hide because SearchableInfo is not part of the API.
+     */
+    public static Cursor getSuggestions(Context context, SearchableInfo searchable, String query) {
+        if (searchable == null) {
+            return null;
+        }
+
+        String authority = searchable.getSuggestAuthority();
+        if (authority == null) {
+            return null;
+        }
+
+        Uri.Builder uriBuilder = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(authority);
+
+        // if content path provided, insert it now
+        final String contentPath = searchable.getSuggestPath();
+        if (contentPath != null) {
+            uriBuilder.appendEncodedPath(contentPath);
+        }
+
+        // append standard suggestion query path 
+        uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY);
+
+        // get the query selection, may be null
+        String selection = searchable.getSuggestSelection();
+        // inject query, either as selection args or inline
+        String[] selArgs = null;
+        if (selection != null) {    // use selection if provided
+            selArgs = new String[] { query };
+        } else {                    // no selection, use REST pattern
+            uriBuilder.appendPath(query);
+        }
+
+        Uri uri = uriBuilder
+                .query("")     // TODO: Remove, workaround for a bug in Uri.writeToParcel()
+                .fragment("")  // TODO: Remove, workaround for a bug in Uri.writeToParcel()
+                .build();
+
+        // finally, make the query
+        return context.getContentResolver().query(uri, null, selection, selArgs, null);
+    }
+     
 }
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
new file mode 100644
index 0000000..af2a321
--- /dev/null
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -0,0 +1,347 @@
+/*
+ * 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.app;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources.NotFoundException;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.server.search.SearchableInfo;
+import android.text.Html;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
+import android.widget.ImageView;
+import android.widget.ResourceCursorAdapter;
+import android.widget.TextView;
+
+import java.io.FileNotFoundException;
+import java.util.WeakHashMap;
+
+/**
+ * Provides the contents for the suggestion drop-down list.in {@link SearchDialog}.
+ * 
+ * @hide
+ */
+class SuggestionsAdapter extends ResourceCursorAdapter {
+    private static final boolean DBG = false;
+    private static final String LOG_TAG = "SuggestionsAdapter";
+    
+    private SearchableInfo mSearchable;
+    private Context mProviderContext;
+    private WeakHashMap<String, Drawable> mOutsideDrawablesCache;
+
+    // Cached column indexes, updated when the cursor changes. 
+    private int mFormatCol;
+    private int mText1Col;
+    private int mText2Col;
+    private int mIconName1Col;
+    private int mIconName2Col;
+    private int mIconBitmap1Col;
+    private int mIconBitmap2Col;
+    
+    public SuggestionsAdapter(Context context, SearchableInfo searchable,
+            WeakHashMap<String, Drawable> outsideDrawablesCache) {
+        super(context,
+                com.android.internal.R.layout.search_dropdown_item_icons_2line,
+                null,   // no initial cursor
+                true);  // auto-requery
+        mSearchable = searchable;
+        
+        // set up provider resources (gives us icons, etc.)
+        Context activityContext = mSearchable.getActivityContext(mContext);
+        mProviderContext = mSearchable.getProviderContext(mContext, activityContext);
+        
+        mOutsideDrawablesCache = outsideDrawablesCache;
+    }
+    
+    /**
+     * Overridden to always return <code>false</code>, since we cannot be sure that
+     * suggestion sources return stable IDs.
+     */
+    @Override
+    public boolean hasStableIds() {
+        return false;
+    }
+
+    /**
+     * Use the search suggestions provider to obtain a live cursor.  This will be called
+     * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions).
+     * The results will be processed in the UI thread and changeCursor() will be called.
+     */
+    @Override
+    public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
+        if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")");
+        String query = (constraint == null) ? "" : constraint.toString();
+        try {
+            return SearchManager.getSuggestions(mContext, mSearchable, query);
+        } catch (RuntimeException e) {
+            Log.w(LOG_TAG, "Search suggestions query threw an exception.", e);
+            return null;
+        }
+    }
+    
+    /**
+     * Cache columns.
+     */
+    @Override
+    public void changeCursor(Cursor c) {
+        if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")");
+        super.changeCursor(c);
+        if (c != null) {
+            mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
+            mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
+            mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
+            mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
+            mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
+            mIconBitmap1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1_BITMAP);
+            mIconBitmap2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2_BITMAP);
+        }
+    }
+    
+    /**
+     * Tags the view with cached child view look-ups.
+     */
+    @Override
+    public View newView(Context context, Cursor cursor, ViewGroup parent) {
+        View v = super.newView(context, cursor, parent);
+        v.setTag(new ChildViewCache(v));
+        return v;
+    }
+    
+    /**
+     * Cache of the child views of drop-drown list items, to avoid looking up the children
+     * each time the contents of a list item are changed.
+     */
+    private final static class ChildViewCache {
+        public final TextView mText1;
+        public final TextView mText2;
+        public final ImageView mIcon1;
+        public final ImageView mIcon2;
+        
+        public ChildViewCache(View v) {
+            mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1);
+            mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2);
+            mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1);
+            mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2);
+        }
+    }
+    
+    @Override
+    public void bindView(View view, Context context, Cursor cursor) {
+        ChildViewCache views = (ChildViewCache) view.getTag();
+        boolean isHtml = false;
+        if (mFormatCol >= 0) {
+            String format = cursor.getString(mFormatCol);
+            isHtml = "html".equals(format);    
+        }
+        setViewText(cursor, views.mText1, mText1Col, isHtml);
+        setViewText(cursor, views.mText2, mText2Col, isHtml);
+        setViewIcon(cursor, views.mIcon1, mIconBitmap1Col, mIconName1Col);
+        setViewIcon(cursor, views.mIcon2, mIconBitmap2Col, mIconName2Col);
+    }
+    
+    private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) {
+        if (v == null) {
+            return;
+        }
+        CharSequence text = null;
+        if (textCol >= 0) {
+            String str = cursor.getString(textCol);
+            text = (str != null && isHtml) ? Html.fromHtml(str) : str;
+        }
+        // Set the text even if it's null, since we need to clear any previous text.
+        v.setText(text);
+        
+        if (TextUtils.isEmpty(text)) {
+            v.setVisibility(View.GONE);
+        } else {
+            v.setVisibility(View.VISIBLE);
+        }
+    }
+    
+    private void setViewIcon(Cursor cursor, ImageView v, int iconBitmapCol, int iconNameCol) {
+        if (v == null) {
+            return;
+        }
+        Drawable drawable = null;
+        // First try the bitmap column
+        if (iconBitmapCol >= 0) {
+            byte[] data = cursor.getBlob(iconBitmapCol);
+            if (data != null) {
+                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+                if (bitmap != null) {
+                    drawable = new BitmapDrawable(bitmap);
+                }
+            }
+        }
+        // If there was no bitmap, try the icon resource column.
+        if (drawable == null && iconNameCol >= 0) {
+            String value = cursor.getString(iconNameCol);
+            drawable = getDrawableFromResourceValue(value);
+        }
+        // Set the icon even if the drawable is null, since we need to clear any
+        // previous icon.
+        v.setImageDrawable(drawable);
+        
+        if (drawable == null) {
+            v.setVisibility(View.GONE);
+        } else {
+            v.setVisibility(View.VISIBLE);
+        }
+    }
+    
+    /**
+     * Gets the text to show in the query field when a suggestion is selected.
+     * 
+     * @param cursor The Cursor to read the suggestion data from. The Cursor should already 
+     *        be moved to the suggestion that is to be read from.
+     * @return The text to show, or <code>null</code> if the query should not be
+     *         changed when selecting this suggestion.
+     */
+    @Override
+    public CharSequence convertToString(Cursor cursor) {
+        if (cursor == null) {
+            return null;
+        }
+        
+        String query = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_QUERY);
+        if (query != null) {
+            return query;
+        }
+        
+        if (mSearchable.mQueryRewriteFromData) {
+            String data = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_INTENT_DATA);
+            if (data != null) {
+                return data;
+            }
+        }
+        
+        if (mSearchable.mQueryRewriteFromText) {
+            String text1 = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_TEXT_1);
+            if (text1 != null) {
+                return text1;
+            }
+        }
+        
+        return null;
+    }
+    
+    /**
+     * This method is overridden purely to provide a bit of protection against
+     * flaky content providers.
+     * 
+     * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
+     */
+    @Override 
+    public View getView(int position, View convertView, ViewGroup parent) {
+        try {
+            return super.getView(position, convertView, parent);
+        } catch (RuntimeException e) {
+            Log.w(LOG_TAG, "Search suggestions cursor threw exception.", e);
+            // Put exception string in item title
+            View v = newView(mContext, mCursor, parent);
+            if (v != null) {
+                ChildViewCache views = (ChildViewCache) v.getTag(); 
+                TextView tv = views.mText1;
+                tv.setText(e.toString());
+            }
+            return v;
+        }
+    }
+    
+    /**
+     * Gets a drawable given a value provided by a suggestion provider.
+     * 
+     * This value could be just the string value of a resource id
+     * (e.g., "2130837524"), in which case we will try to retrieve a drawable from
+     * the provider's resources. If the value is not an integer, it is
+     * treated as a Uri and opened with  
+     * {@link ContentResolver#openOutputStream(android.net.Uri, String)}.
+     *
+     * All resources and URIs are read using the suggestion provider's context.
+     *
+     * If the string is not formatted as expected, or no drawable can be found for
+     * the provided value, this method returns null.
+     * 
+     * @param drawableId a string like "2130837524",
+     *        "android.resource://com.android.alarmclock/2130837524",
+     *        or "content://contacts/photos/253".
+     * @return a Drawable, or null if none found
+     */
+    private Drawable getDrawableFromResourceValue(String drawableId) {
+        if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) {
+            return null;
+        }
+        
+        // First, check the cache.
+        Drawable drawable = mOutsideDrawablesCache.get(drawableId);
+        if (drawable != null) return drawable;
+
+        try {
+            // Not cached, try using it as a plain resource ID in the provider's context.
+            int resourceId = Integer.parseInt(drawableId);
+            drawable = mProviderContext.getResources().getDrawable(resourceId);
+        } catch (NumberFormatException nfe) {
+            // The id was not an integer resource id.
+            // Let the ContentResolver handle content, android.resource and file URIs.
+            try {
+                Uri uri = Uri.parse(drawableId);
+                drawable = Drawable.createFromStream(
+                        mProviderContext.getContentResolver().openInputStream(uri),
+                        null);
+            } catch (FileNotFoundException fnfe) {
+                // drawable = null;
+            }
+                    
+            // If we got a drawable for this resource id, then stick it in the
+            // map so we don't do this lookup again.
+            if (drawable != null) {
+                mOutsideDrawablesCache.put(drawableId, drawable);
+            }
+        } catch (NotFoundException nfe) {
+            // Resource could not be found
+            // drawable = null;
+        }
+        
+        return drawable;
+    }
+    
+    /**
+     * Gets the value of a string column by name.
+     * 
+     * @param cursor Cursor to read the value from.
+     * @param columnName The name of the column to read.
+     * @return The value of the given column, or <code>null</null>
+     *         if the cursor does not contain the given column.
+     */
+    public static String getColumnString(Cursor cursor, String columnName) {
+        int col = cursor.getColumnIndex(columnName);
+        if (col == -1) {
+            return null;
+        }
+        return cursor.getString(col);
+    }
+
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 600dfa4..a301449 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -527,6 +527,16 @@
     public abstract int getWallpaperDesiredMinimumHeight();
 
     /**
+     * Returns the scale in which the application will be drawn on the
+     * screen. This is usually 1.0f if the application supports the device's
+     * resolution/density. This will be 1.5f, for example, if the application
+     * that supports only 160 density runs on 240 density screen.
+     *
+     * @hide
+     */
+    public abstract float getApplicationScale();
+
+    /**
      * Change the current system wallpaper to a bitmap.  The given bitmap is
      * converted to a PNG and stored as the wallpaper.  On success, the intent
      * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 36e1c34..25b2cae 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -419,4 +419,12 @@
         throws PackageManager.NameNotFoundException {
         return mBase.createPackageContext(packageName, flags);
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public float getApplicationScale() {
+        return mBase.getApplicationScale();
+    }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 99cf34c..b3e81d7 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -508,6 +508,8 @@
  *     <li> {@link #ACTION_PACKAGE_DATA_CLEARED}
  *     <li> {@link #ACTION_UID_REMOVED}
  *     <li> {@link #ACTION_BATTERY_CHANGED}
+ *     <li> {@link #ACTION_POWER_CONNECTED}
+ *     <li> {@link #ACTION_POWER_DISCONNECTED} 
  * </ul>
  *
  * <h3>Standard Categories</h3>
@@ -1250,6 +1252,24 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW";
     /**
+     * Broadcast Action:  External power has been connected to the device.
+     * This is intended for applications that wish to register specifically to this notification.
+     * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to
+     * stay active to receive this notification.  This action can be used to implement actions
+     * that wait until power is available to trigger.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
+    /**
+     * Broadcast Action:  External power has been removed from the device.
+     * This is intended for applications that wish to register specifically to this notification.
+     * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to
+     * stay active to receive this notification.  This action can be used to implement actions
+     * that wait until power is available to trigger. 
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";    
+    /**
      * Broadcast Action:  Indicates low memory condition on the device
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -4370,12 +4390,35 @@
 
     @Override
     public String toString() {
-        StringBuilder   b = new StringBuilder();
+        StringBuilder   b = new StringBuilder(128);
 
-        b.append("Intent {");
-        if (mAction != null) b.append(" action=").append(mAction);
+        b.append("Intent { ");
+        toShortString(b, true, true);
+        b.append(" }");
+
+        return b.toString();
+    }
+
+    /** @hide */
+    public String toShortString(boolean comp, boolean extras) {
+        StringBuilder   b = new StringBuilder(128);
+        toShortString(b, comp, extras);
+        return b.toString();
+    }
+    
+    /** @hide */
+    public void toShortString(StringBuilder b, boolean comp, boolean extras) {
+        boolean first = true;
+        if (mAction != null) {
+            b.append("act=").append(mAction);
+            first = false;
+        }
         if (mCategories != null) {
-            b.append(" categories={");
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("cat=[");
             Iterator<String> i = mCategories.iterator();
             boolean didone = false;
             while (i.hasNext()) {
@@ -4383,20 +4426,48 @@
                 didone = true;
                 b.append(i.next());
             }
-            b.append("}");
+            b.append("]");
         }
-        if (mData != null) b.append(" data=").append(mData);
-        if (mType != null) b.append(" type=").append(mType);
-        if (mFlags != 0) b.append(" flags=0x").append(Integer.toHexString(mFlags));
-        if (mComponent != null) b.append(" comp=").append(mComponent.toShortString());
-        if (mExtras != null) b.append(" (has extras)");
-        b.append(" }");
-
-        return b.toString();
+        if (mData != null) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("dat=").append(mData);
+        }
+        if (mType != null) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("typ=").append(mType);
+        }
+        if (mFlags != 0) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("flg=0x").append(Integer.toHexString(mFlags));
+        }
+        if (comp && mComponent != null) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("cmp=").append(mComponent.flattenToShortString());
+        }
+        if (extras && mExtras != null) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("(has extras)");
+        }
     }
 
     public String toURI() {
-        StringBuilder uri = new StringBuilder(mData != null ? mData.toString() : "");
+        StringBuilder uri = new StringBuilder(128);
+        if (mData != null) uri.append(mData.toString());
 
         uri.append("#Intent;");
 
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 9b190df..e5c5dc8 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1254,47 +1254,71 @@
     }
 
     public void dump(Printer du, String prefix) {
+        StringBuilder sb = new StringBuilder(256);
         if (mActions.size() > 0) {
             Iterator<String> it = mActions.iterator();
             while (it.hasNext()) {
-               du.println(prefix + "Action: \"" + it.next() + "\"");
+                sb.setLength(0);
+                sb.append(prefix); sb.append("Action: \"");
+                        sb.append(it.next()); sb.append("\"");
+                du.println(sb.toString());
             }
         }
         if (mCategories != null) {
             Iterator<String> it = mCategories.iterator();
             while (it.hasNext()) {
-                du.println(prefix + "Category: \"" + it.next() + "\"");
+                sb.setLength(0);
+                sb.append(prefix); sb.append("Category: \"");
+                        sb.append(it.next()); sb.append("\"");
+                du.println(sb.toString());
             }
         }
         if (mDataSchemes != null) {
             Iterator<String> it = mDataSchemes.iterator();
             while (it.hasNext()) {
-                du.println(prefix + "Data Scheme: \"" + it.next() + "\"");
+                sb.setLength(0);
+                sb.append(prefix); sb.append("Scheme: \"");
+                        sb.append(it.next()); sb.append("\"");
+                du.println(sb.toString());
             }
         }
         if (mDataAuthorities != null) {
             Iterator<AuthorityEntry> it = mDataAuthorities.iterator();
             while (it.hasNext()) {
                 AuthorityEntry ae = it.next();
-                du.println(prefix + "Data Authority: \"" + ae.mHost + "\":"
-                        + ae.mPort + (ae.mWild ? " WILD" : ""));
+                sb.setLength(0);
+                sb.append(prefix); sb.append("Authority: \"");
+                        sb.append(ae.mHost); sb.append("\": ");
+                        sb.append(ae.mPort);
+                if (ae.mWild) sb.append(" WILD");
+                du.println(sb.toString());
             }
         }
         if (mDataPaths != null) {
             Iterator<PatternMatcher> it = mDataPaths.iterator();
             while (it.hasNext()) {
                 PatternMatcher pe = it.next();
-                du.println(prefix + "Data Path: \"" + pe + "\"");
+                sb.setLength(0);
+                sb.append(prefix); sb.append("Path: \"");
+                        sb.append(pe); sb.append("\"");
+                du.println(sb.toString());
             }
         }
         if (mDataTypes != null) {
             Iterator<String> it = mDataTypes.iterator();
             while (it.hasNext()) {
-                du.println(prefix + "Data Type: \"" + it.next() + "\"");
+                sb.setLength(0);
+                sb.append(prefix); sb.append("Type: \"");
+                        sb.append(it.next()); sb.append("\"");
+                du.println(sb.toString());
             }
         }
-        du.println(prefix + "mPriority=" + mPriority
-                + ", mHasPartialTypes=" + mHasPartialTypes);
+        if (mPriority != 0 || mHasPartialTypes) {
+            sb.setLength(0);
+            sb.append(prefix); sb.append("mPriority="); sb.append(mPriority);
+                    sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes);
+            du.println(sb.toString());
+        }
     }
 
     public static final Parcelable.Creator<IntentFilter> CREATOR
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index a98e6d5..72ec469 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -19,6 +19,7 @@
 import android.net.Uri;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.regex.Pattern;
 
 /**
@@ -200,7 +201,8 @@
      */
     public int match(Uri uri)
     {
-        final int li = uri.getPathSegments().size();
+        final List<String> pathSegments = uri.getPathSegments();
+        final int li = pathSegments.size();
 
         UriMatcher node = this;
 
@@ -209,7 +211,7 @@
         }
 
         for (int i=-1; i<li; i++) {
-            String u = i < 0 ? uri.getAuthority() : uri.getPathSegments().get(i);
+            String u = i < 0 ? uri.getAuthority() : pathSegments.get(i);
             ArrayList<UriMatcher> list = node.mChildren;
             if (list == null) {
                 break;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 8d727ed..173057c 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -161,6 +161,14 @@
      */
     public int uid;
     
+
+    /**
+     * The list of densities in DPI that application supprots. This
+     * field is only set if the {@link PackageManager#GET_SUPPORTS_DENSITIES} flag was
+     * used when retrieving the structure.
+     */
+    public int[] supportsDensities;
+
     /**
      * When false, indicates that all components within this application are
      * considered disabled, regardless of their individually set enabled status.
@@ -181,8 +189,9 @@
         pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
         pw.println(prefix + "dataDir=" + dataDir);
         pw.println(prefix + "enabled=" + enabled);
-        pw.println(prefix+"manageSpaceActivityName="+manageSpaceActivityName);
-        pw.println(prefix+"description=0x"+Integer.toHexString(descriptionRes));
+        pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
+        pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
+        pw.println(prefix + "supportsDensities=" + supportsDensities);
         super.dumpBack(pw, prefix);
     }
     
@@ -228,6 +237,7 @@
         enabled = orig.enabled;
         manageSpaceActivityName = orig.manageSpaceActivityName;
         descriptionRes = orig.descriptionRes;
+        supportsDensities = orig.supportsDensities;
     }
 
 
@@ -257,6 +267,7 @@
         dest.writeInt(enabled ? 1 : 0);
         dest.writeString(manageSpaceActivityName);
         dest.writeInt(descriptionRes);
+        dest.writeIntArray(supportsDensities);
     }
 
     public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -285,8 +296,9 @@
         enabled = source.readInt() != 0;
         manageSpaceActivityName = source.readString();
         descriptionRes = source.readInt();
+        supportsDensities = source.createIntArray();
     }
-    
+
     /**
      * Retrieve the textual description of the application.  This
      * will call back on the given PackageManager to load the description from
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3e94734..9e06666 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -166,6 +166,12 @@
     public static final int GET_CONFIGURATIONS = 0x00004000;
 
     /**
+     * {@link ApplicationInfo} flag: return the
+     * {@link ApplicationInfo#supportsDensities} that the package supports.
+     */
+    public static final int GET_SUPPORTS_DENSITIES    = 0x00008000;
+
+    /**
      * Permission check result: this is returned by {@link #checkPermission}
      * if the permission has been granted to the given package.
      */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2dcb483..f9c4984 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -45,6 +45,7 @@
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
@@ -64,6 +65,48 @@
     private static final Object mSync = new Object();
     private static WeakReference<byte[]> mReadBuffer;
 
+    static class ParsePackageItemArgs {
+        final Package owner;
+        final String[] outError;
+        final int nameRes;
+        final int labelRes;
+        final int iconRes;
+        
+        String tag;
+        TypedArray sa;
+        
+        ParsePackageItemArgs(Package _owner, String[] _outError,
+                int _nameRes, int _labelRes, int _iconRes) {
+            owner = _owner;
+            outError = _outError;
+            nameRes = _nameRes;
+            labelRes = _labelRes;
+            iconRes = _iconRes;
+        }
+    }
+    
+    static class ParseComponentArgs extends ParsePackageItemArgs {
+        final String[] sepProcesses;
+        final int processRes;
+        final int enabledRes;
+        int flags;
+        
+        ParseComponentArgs(Package _owner, String[] _outError,
+                int _nameRes, int _labelRes, int _iconRes,
+                String[] _sepProcesses, int _processRes,int _enabledRes) {
+            super(_owner, _outError, _nameRes, _labelRes, _iconRes);
+            sepProcesses = _sepProcesses;
+            processRes = _processRes;
+            enabledRes = _enabledRes;
+        }
+    }
+    
+    private ParsePackageItemArgs mParseInstrumentationArgs;
+    private ParseComponentArgs mParseActivityArgs;
+    private ParseComponentArgs mParseActivityAliasArgs;
+    private ParseComponentArgs mParseServiceArgs;
+    private ParseComponentArgs mParseProviderArgs;
+    
     /** If set to true, we will only allow package files that exactly match
      *  the DTD.  Otherwise, we try to get as much from the package as we
      *  can without failing.  This should normally be set to false, to
@@ -557,6 +600,11 @@
         throws XmlPullParserException, IOException {
         AttributeSet attrs = parser;
 
+        mParseInstrumentationArgs = null;
+        mParseActivityArgs = null;
+        mParseServiceArgs = null;
+        mParseProviderArgs = null;
+        
         String pkgName = parsePackageName(parser, attrs, flags, outError);
         if (pkgName == null) {
             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
@@ -593,8 +641,6 @@
         }
         sa.recycle();
 
-        final int innerDepth = parser.getDepth();
-
         int outerDepth = parser.getDepth();
         while ((type=parser.next()) != parser.END_DOCUMENT
                && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -726,6 +772,14 @@
             pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
         }
 
+        int size = pkg.supportsDensityList.size();
+        if (size > 0) {
+            int densities[] = pkg.supportsDensities = new int[size];
+            List<Integer> densityList = pkg.supportsDensityList;
+            for (int i = 0; i < size; i++) {
+                densities[i] = densityList.get(i);
+            }
+        }
         return pkg;
     }
 
@@ -950,20 +1004,24 @@
         TypedArray sa = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestInstrumentation);
 
-        Instrumentation a = new Instrumentation(owner);
-
-        if (!parsePackageItemInfo(owner, a.info, outError, "<instrumentation>", sa,
-                com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
-                com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
-                com.android.internal.R.styleable.AndroidManifestInstrumentation_icon)) {
+        if (mParseInstrumentationArgs == null) {
+            mParseInstrumentationArgs = new ParsePackageItemArgs(owner, outError,
+                    com.android.internal.R.styleable.AndroidManifestInstrumentation_name,
+                    com.android.internal.R.styleable.AndroidManifestInstrumentation_label,
+                    com.android.internal.R.styleable.AndroidManifestInstrumentation_icon);
+            mParseInstrumentationArgs.tag = "<instrumentation>";
+        }
+        
+        mParseInstrumentationArgs.sa = sa;
+        
+        Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
+                new InstrumentationInfo());
+        if (outError[0] != null) {
             sa.recycle();
             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
             return null;
         }
 
-        a.component = new ComponentName(owner.applicationInfo.packageName,
-                a.info.name);
-
         String str;
         str = sa.getNonResourceString(
                 com.android.internal.R.styleable.AndroidManifestInstrumentation_targetPackage);
@@ -1140,7 +1198,7 @@
                 owner.providers.add(p);
 
             } else if (tagName.equals("activity-alias")) {
-                Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError, false);
+                Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
                 if (a == null) {
                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                     return false;
@@ -1173,6 +1231,21 @@
 
                 XmlUtils.skipCurrentTag(parser);
 
+            } else if (tagName.equals("supports-density")) {
+                sa = res.obtainAttributes(attrs,
+                        com.android.internal.R.styleable.AndroidManifestSupportsDensity);
+
+                int density = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1);
+
+                sa.recycle();
+
+                if (density != -1 && !owner.supportsDensityList.contains(density)) {
+                    owner.supportsDensityList.add(density);
+                }
+
+                XmlUtils.skipCurrentTag(parser);
+
             } else {
                 if (!RIGID_PARSER) {
                     Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
@@ -1239,22 +1312,29 @@
 
         return outError[0] == null;
     }
-
+    
     private Activity parseActivity(Package owner, Resources res,
             XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
             boolean receiver) throws XmlPullParserException, IOException {
         TypedArray sa = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestActivity);
 
-        Activity a = new Activity(owner);
-
-        if (!parseComponentInfo(owner, flags, a.info, outError,
-                receiver ? "<receiver>" : "<activity>", sa,
-                com.android.internal.R.styleable.AndroidManifestActivity_name,
-                com.android.internal.R.styleable.AndroidManifestActivity_label,
-                com.android.internal.R.styleable.AndroidManifestActivity_icon,
-                com.android.internal.R.styleable.AndroidManifestActivity_process,
-                com.android.internal.R.styleable.AndroidManifestActivity_enabled)) {
+        if (mParseActivityArgs == null) {
+            mParseActivityArgs = new ParseComponentArgs(owner, outError,
+                    com.android.internal.R.styleable.AndroidManifestActivity_name,
+                    com.android.internal.R.styleable.AndroidManifestActivity_label,
+                    com.android.internal.R.styleable.AndroidManifestActivity_icon,
+                    mSeparateProcesses,
+                    com.android.internal.R.styleable.AndroidManifestActivity_process,
+                    com.android.internal.R.styleable.AndroidManifestActivity_enabled);
+        }
+        
+        mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
+        mParseActivityArgs.sa = sa;
+        mParseActivityArgs.flags = flags;
+        
+        Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
+        if (outError[0] != null) {
             sa.recycle();
             return null;
         }
@@ -1266,9 +1346,6 @@
                     com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
         }
 
-        a.component = new ComponentName(owner.applicationInfo.packageName,
-                a.info.name);
-
         a.info.theme = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
 
@@ -1412,8 +1489,8 @@
     }
 
     private Activity parseActivityAlias(Package owner, Resources res,
-            XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
-            boolean receiver) throws XmlPullParserException, IOException {
+            XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
+            throws XmlPullParserException, IOException {
         TypedArray sa = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestActivityAlias);
 
@@ -1432,7 +1509,20 @@
             return null;
         }
 
-        Activity a = new Activity(owner);
+        if (mParseActivityAliasArgs == null) {
+            mParseActivityAliasArgs = new ParseComponentArgs(owner, outError,
+                    com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
+                    com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
+                    com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
+                    mSeparateProcesses,
+                    0,
+                    com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
+            mParseActivityAliasArgs.tag = "<activity-alias>";
+        }
+        
+        mParseActivityAliasArgs.sa = sa;
+        mParseActivityAliasArgs.flags = flags;
+        
         Activity target = null;
 
         final int NA = owner.activities.size();
@@ -1451,26 +1541,21 @@
             return null;
         }
 
-        a.info.targetActivity = targetActivity;
-
-        a.info.configChanges = target.info.configChanges;
-        a.info.flags = target.info.flags;
-        a.info.icon = target.info.icon;
-        a.info.labelRes = target.info.labelRes;
-        a.info.launchMode = target.info.launchMode;
-        a.info.nonLocalizedLabel = target.info.nonLocalizedLabel;
-        a.info.processName = target.info.processName;
-        a.info.screenOrientation = target.info.screenOrientation;
-        a.info.taskAffinity = target.info.taskAffinity;
-        a.info.theme = target.info.theme;
-
-        if (!parseComponentInfo(owner, flags, a.info, outError,
-                receiver ? "<receiver>" : "<activity>", sa,
-                com.android.internal.R.styleable.AndroidManifestActivityAlias_name,
-                com.android.internal.R.styleable.AndroidManifestActivityAlias_label,
-                com.android.internal.R.styleable.AndroidManifestActivityAlias_icon,
-                0,
-                com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled)) {
+        ActivityInfo info = new ActivityInfo();
+        info.targetActivity = targetActivity;
+        info.configChanges = target.info.configChanges;
+        info.flags = target.info.flags;
+        info.icon = target.info.icon;
+        info.labelRes = target.info.labelRes;
+        info.nonLocalizedLabel = target.info.nonLocalizedLabel;
+        info.launchMode = target.info.launchMode;
+        info.processName = target.info.processName;
+        info.screenOrientation = target.info.screenOrientation;
+        info.taskAffinity = target.info.taskAffinity;
+        info.theme = target.info.theme;
+        
+        Activity a = new Activity(mParseActivityAliasArgs, info);
+        if (outError[0] != null) {
             sa.recycle();
             return null;
         }
@@ -1482,9 +1567,6 @@
                     com.android.internal.R.styleable.AndroidManifestActivityAlias_exported, false);
         }
 
-        a.component = new ComponentName(owner.applicationInfo.packageName,
-                a.info.name);
-
         String str;
         str = sa.getNonResourceString(
                 com.android.internal.R.styleable.AndroidManifestActivityAlias_permission);
@@ -1548,14 +1630,22 @@
         TypedArray sa = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestProvider);
 
-        Provider p = new Provider(owner);
-
-        if (!parseComponentInfo(owner, flags, p.info, outError, "<provider>", sa,
-                com.android.internal.R.styleable.AndroidManifestProvider_name,
-                com.android.internal.R.styleable.AndroidManifestProvider_label,
-                com.android.internal.R.styleable.AndroidManifestProvider_icon,
-                com.android.internal.R.styleable.AndroidManifestProvider_process,
-                com.android.internal.R.styleable.AndroidManifestProvider_enabled)) {
+        if (mParseProviderArgs == null) {
+            mParseProviderArgs = new ParseComponentArgs(owner, outError,
+                    com.android.internal.R.styleable.AndroidManifestProvider_name,
+                    com.android.internal.R.styleable.AndroidManifestProvider_label,
+                    com.android.internal.R.styleable.AndroidManifestProvider_icon,
+                    mSeparateProcesses,
+                    com.android.internal.R.styleable.AndroidManifestProvider_process,
+                    com.android.internal.R.styleable.AndroidManifestProvider_enabled);
+            mParseProviderArgs.tag = "<provider>";
+        }
+        
+        mParseProviderArgs.sa = sa;
+        mParseProviderArgs.flags = flags;
+        
+        Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
+        if (outError[0] != null) {
             sa.recycle();
             return null;
         }
@@ -1563,9 +1653,6 @@
         p.info.exported = sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestProvider_exported, true);
 
-        p.component = new ComponentName(owner.applicationInfo.packageName,
-                p.info.name);
-
         String cpname = sa.getNonResourceString(
                 com.android.internal.R.styleable.AndroidManifestProvider_authorities);
 
@@ -1706,14 +1793,22 @@
         TypedArray sa = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestService);
 
-        Service s = new Service(owner);
-
-        if (!parseComponentInfo(owner, flags, s.info, outError, "<service>", sa,
-                com.android.internal.R.styleable.AndroidManifestService_name,
-                com.android.internal.R.styleable.AndroidManifestService_label,
-                com.android.internal.R.styleable.AndroidManifestService_icon,
-                com.android.internal.R.styleable.AndroidManifestService_process,
-                com.android.internal.R.styleable.AndroidManifestService_enabled)) {
+        if (mParseServiceArgs == null) {
+            mParseServiceArgs = new ParseComponentArgs(owner, outError,
+                    com.android.internal.R.styleable.AndroidManifestService_name,
+                    com.android.internal.R.styleable.AndroidManifestService_label,
+                    com.android.internal.R.styleable.AndroidManifestService_icon,
+                    mSeparateProcesses,
+                    com.android.internal.R.styleable.AndroidManifestService_process,
+                    com.android.internal.R.styleable.AndroidManifestService_enabled);
+            mParseServiceArgs.tag = "<service>";
+        }
+        
+        mParseServiceArgs.sa = sa;
+        mParseServiceArgs.flags = flags;
+        
+        Service s = new Service(mParseServiceArgs, new ServiceInfo());
+        if (outError[0] != null) {
             sa.recycle();
             return null;
         }
@@ -1725,9 +1820,6 @@
                     com.android.internal.R.styleable.AndroidManifestService_exported, false);
         }
 
-        s.component = new ComponentName(owner.applicationInfo.packageName,
-                s.info.name);
-
         String str = sa.getNonResourceString(
                 com.android.internal.R.styleable.AndroidManifestService_permission);
         if (str == null) {
@@ -2035,6 +2127,9 @@
         // We store the application meta-data independently to avoid multiple unwanted references
         public Bundle mAppMetaData = null;
 
+        public final ArrayList<Integer> supportsDensityList = new ArrayList<Integer>();
+        public int[] supportsDensities = null;
+
         // If this is a 3rd party app, this is the path of the zip file.
         public String mPath;
 
@@ -2084,16 +2179,75 @@
 
     public static class Component<II extends IntentInfo> {
         public final Package owner;
-        public final ArrayList<II> intents = new ArrayList<II>(0);
-        public ComponentName component;
+        public final ArrayList<II> intents;
+        public final ComponentName component;
+        public final String componentShortName;
         public Bundle metaData;
 
         public Component(Package _owner) {
             owner = _owner;
+            intents = null;
+            component = null;
+            componentShortName = null;
+        }
+
+        public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
+            owner = args.owner;
+            intents = new ArrayList<II>(0);
+            String name = args.sa.getNonResourceString(args.nameRes);
+            if (name == null) {
+                component = null;
+                componentShortName = null;
+                args.outError[0] = args.tag + " does not specify android:name";
+                return;
+            }
+
+            outInfo.name
+                = buildClassName(owner.applicationInfo.packageName, name, args.outError);
+            if (outInfo.name == null) {
+                component = null;
+                componentShortName = null;
+                args.outError[0] = args.tag + " does not have valid android:name";
+                return;
+            }
+
+            component = new ComponentName(owner.applicationInfo.packageName,
+                    outInfo.name);
+            componentShortName = component.flattenToShortString();
+
+            int iconVal = args.sa.getResourceId(args.iconRes, 0);
+            if (iconVal != 0) {
+                outInfo.icon = iconVal;
+                outInfo.nonLocalizedLabel = null;
+            }
+
+            TypedValue v = args.sa.peekValue(args.labelRes);
+            if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
+                outInfo.nonLocalizedLabel = v.coerceToString();
+            }
+
+            outInfo.packageName = owner.packageName;
+        }
+
+        public Component(final ParseComponentArgs args, final ComponentInfo outInfo) {
+            this(args, (PackageItemInfo)outInfo);
+            if (args.outError[0] != null) {
+                return;
+            }
+
+            if (args.processRes != 0) {
+                outInfo.processName = buildProcessName(owner.applicationInfo.packageName,
+                        owner.applicationInfo.processName, args.sa.getNonResourceString(args.processRes),
+                        args.flags, args.sepProcesses, args.outError);
+            }
+            outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
         }
 
         public Component(Component<II> clone) {
             owner = clone.owner;
+            intents = clone.intents;
+            component = clone.component;
+            componentShortName = clone.componentShortName;
             metaData = clone.metaData;
         }
     }
@@ -2149,6 +2303,10 @@
                 && p.usesLibraryFiles != null) {
             return true;
         }
+        if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0
+            && p.supportsDensities != null) {
+            return true;
+        }
         return false;
     }
 
@@ -2166,6 +2324,9 @@
         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
             ai.sharedLibraryFiles = p.usesLibraryFiles;
         }
+        if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) {
+            ai.supportsDensities = p.supportsDensities;
+        }
         return ai;
     }
 
@@ -2192,14 +2353,14 @@
     }
 
     public final static class Activity extends Component<ActivityIntentInfo> {
-        public final ActivityInfo info =
-                new ActivityInfo();
+        public final ActivityInfo info;
 
-        public Activity(Package _owner) {
-            super(_owner);
-            info.applicationInfo = owner.applicationInfo;
+        public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
+            super(args, _info);
+            info = _info;
+            info.applicationInfo = args.owner.applicationInfo;
         }
-
+        
         public String toString() {
             return "Activity{"
                 + Integer.toHexString(System.identityHashCode(this))
@@ -2221,14 +2382,14 @@
     }
 
     public final static class Service extends Component<ServiceIntentInfo> {
-        public final ServiceInfo info =
-                new ServiceInfo();
+        public final ServiceInfo info;
 
-        public Service(Package _owner) {
-            super(_owner);
-            info.applicationInfo = owner.applicationInfo;
+        public Service(final ParseComponentArgs args, final ServiceInfo _info) {
+            super(args, _info);
+            info = _info;
+            info.applicationInfo = args.owner.applicationInfo;
         }
-
+        
         public String toString() {
             return "Service{"
                 + Integer.toHexString(System.identityHashCode(this))
@@ -2252,13 +2413,13 @@
         public final ProviderInfo info;
         public boolean syncable;
 
-        public Provider(Package _owner) {
-            super(_owner);
-            info = new ProviderInfo();
-            info.applicationInfo = owner.applicationInfo;
+        public Provider(final ParseComponentArgs args, final ProviderInfo _info) {
+            super(args, _info);
+            info = _info;
+            info.applicationInfo = args.owner.applicationInfo;
             syncable = false;
         }
-
+        
         public Provider(Provider existingProvider) {
             super(existingProvider);
             this.info = existingProvider.info;
@@ -2291,13 +2452,13 @@
     }
 
     public final static class Instrumentation extends Component {
-        public final InstrumentationInfo info =
-                new InstrumentationInfo();
+        public final InstrumentationInfo info;
 
-        public Instrumentation(Package _owner) {
-            super(_owner);
+        public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
+            super(args, _info);
+            info = _info;
         }
-
+        
         public String toString() {
             return "Instrumentation{"
                 + Integer.toHexString(System.identityHashCode(this))
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 956b15a..bb3486c 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -144,11 +144,29 @@
     }
 
     public String toString() {
-        return "{ scale=" + fontScale + " imsi=" + mcc + "/" + mnc
-                + " locale=" + locale
-                + " touch=" + touchscreen + " key=" + keyboard + "/"
-                + keyboardHidden + "/" + hardKeyboardHidden
-                + " nav=" + navigation + " orien=" + orientation + " }";
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("{ scale=");
+        sb.append(fontScale);
+        sb.append(" imsi=");
+        sb.append(mcc);
+        sb.append("/");
+        sb.append(mnc);
+        sb.append(" loc=");
+        sb.append(locale);
+        sb.append(" touch=");
+        sb.append(touchscreen);
+        sb.append(" keys=");
+        sb.append(keyboard);
+        sb.append("/");
+        sb.append(keyboardHidden);
+        sb.append("/");
+        sb.append(hardKeyboardHidden);
+        sb.append(" nav=");
+        sb.append(navigation);
+        sb.append(" orien=");
+        sb.append(orientation);
+        sb.append('}');
+        return sb.toString();
     }
 
     /**
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e020462..665e40c 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -24,6 +24,7 @@
 
 import android.graphics.Movie;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.os.SystemProperties;
@@ -56,12 +57,14 @@
     // Information about preloaded resources.  Note that they are not
     // protected by a lock, because while preloading in zygote we are all
     // single-threaded, and after that these are immutable.
-    private static final SparseArray<Drawable.ConstantState> mPreloadedDrawables
+    private static final SparseArray<Drawable.ConstantState> sPreloadedDrawables
             = new SparseArray<Drawable.ConstantState>();
     private static final SparseArray<ColorStateList> mPreloadedColorStateLists
             = new SparseArray<ColorStateList>();
     private static boolean mPreloaded;
 
+    private final SparseArray<Drawable.ConstantState> mPreloadedDrawables;
+
     /*package*/ final TypedValue mTmpValue = new TypedValue();
 
     // These are protected by the mTmpValue lock.
@@ -82,6 +85,22 @@
     /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
     PluralRules mPluralRule;
 
+    private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() {
+        @Override
+        public void put(int k, Object o) {
+            throw new UnsupportedOperationException();
+        }
+        @Override
+        public void append(int k, Object o) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    @SuppressWarnings("unchecked")
+    private static <T> SparseArray<T> emptySparseArray() {
+        return (SparseArray<T>) EMPTY_ARRAY;
+    }
+
     /**
      * This exception is thrown by the resource APIs when a requested resource
      * can not be found.
@@ -107,11 +126,27 @@
      */
     public Resources(AssetManager assets, DisplayMetrics metrics,
             Configuration config) {
+        this(assets, metrics, config, true);
+    }
+
+    /**
+     * Create a resource with an additional flag for preloaded
+     * drawable cache. Used by {@link ActivityThread}.
+     *
+     * @hide
+     */
+    public Resources(AssetManager assets, DisplayMetrics metrics,
+        Configuration config, boolean usePreloadedCache) {
         mAssets = assets;
         mConfiguration.setToDefaults();
         mMetrics.setToDefaults();
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
+        if (usePreloadedCache) {
+            mPreloadedDrawables = sPreloadedDrawables;
+        } else {
+            mPreloadedDrawables = emptySparseArray();
+        }
     }
 
     /**
@@ -1218,6 +1253,7 @@
                 mMetrics.setTo(metrics);
             }
             mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
+
             String locale = null;
             if (mConfiguration.locale != null) {
                 locale = mConfiguration.locale.getLanguage();
@@ -1653,7 +1689,7 @@
             cs = dr.getConstantState();
             if (cs != null) {
                 if (mPreloading) {
-                    mPreloadedDrawables.put(key, cs);
+                    sPreloadedDrawables.put(key, cs);
                 } else {
                     synchronized (mTmpValue) {
                         //Log.i(TAG, "Saving cached drawable @ #" +
@@ -1883,6 +1919,6 @@
         mMetrics.setToDefaults();
         updateConfiguration(null, null);
         mAssets.ensureStringBlocks();
+        mPreloadedDrawables = sPreloadedDrawables;
     }
 }
-
diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java
index 54457c2..95fa0a2 100644
--- a/core/java/android/ddm/DdmHandleHeap.java
+++ b/core/java/android/ddm/DdmHandleHeap.java
@@ -20,17 +20,20 @@
 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
 import org.apache.harmony.dalvik.ddmc.DdmServer;
 import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
+import android.os.Debug;
 import android.util.Config;
 import android.util.Log;
+import java.io.IOException;
 import java.nio.ByteBuffer;
 
 /**
- * Handle thread-related traffic.
+ * Handle native and virtual heap requests.
  */
 public class DdmHandleHeap extends ChunkHandler {
 
     public static final int CHUNK_HPIF = type("HPIF");
     public static final int CHUNK_HPSG = type("HPSG");
+    public static final int CHUNK_HPDU = type("HPDU");
     public static final int CHUNK_NHSG = type("NHSG");
     public static final int CHUNK_HPGC = type("HPGC");
     public static final int CHUNK_REAE = type("REAE");
@@ -49,6 +52,7 @@
     public static void register() {
         DdmServer.registerHandler(CHUNK_HPIF, mInstance);
         DdmServer.registerHandler(CHUNK_HPSG, mInstance);
+        DdmServer.registerHandler(CHUNK_HPDU, mInstance);
         DdmServer.registerHandler(CHUNK_NHSG, mInstance);
         DdmServer.registerHandler(CHUNK_HPGC, mInstance);
         DdmServer.registerHandler(CHUNK_REAE, mInstance);
@@ -80,6 +84,8 @@
             return handleHPIF(request);
         } else if (type == CHUNK_HPSG) {
             return handleHPSGNHSG(request, false);
+        } else if (type == CHUNK_HPDU) {
+            return handleHPDU(request);
         } else if (type == CHUNK_NHSG) {
             return handleHPSGNHSG(request, true);
         } else if (type == CHUNK_HPGC) {
@@ -97,7 +103,7 @@
     }
 
     /*
-     * Handle a "HeaP InFo request".
+     * Handle a "HeaP InFo" request.
      */
     private Chunk handleHPIF(Chunk request) {
         ByteBuffer in = wrapChunk(request);
@@ -137,6 +143,40 @@
     }
 
     /*
+     * Handle a "HeaP DUmp" request.
+     *
+     * This currently just returns a result code.  We could pull up
+     * the entire contents of the file and return them, but hprof dump
+     * files can be a few megabytes.
+     */
+    private Chunk handleHPDU(Chunk request) {
+        ByteBuffer in = wrapChunk(request);
+        byte result;
+
+        /* get the filename for the output file */
+        int len = in.getInt();
+        String fileName = getString(in, len);
+        if (Config.LOGD)
+            Log.d("ddm-heap", "Heap dump: file='" + fileName + "'");
+
+        try {
+            Debug.dumpHprofData(fileName);
+            result = 0;
+        } catch (UnsupportedOperationException uoe) {
+            Log.w("ddm-heap", "hprof dumps not supported in this VM");
+            result = -1;
+        } catch (IOException ioe) {
+            result = -1;
+        } catch (RuntimeException ioe) {
+            result = -1;
+        }
+
+        /* create a non-empty reply so the handler fires on completion */
+        byte[] reply = { result };
+        return new Chunk(CHUNK_HPDU, reply, 0, reply.length);
+    }
+
+    /*
      * Handle a "HeaP Garbage Collection" request.
      */
     private Chunk handleHPGC(Chunk request) {
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index e4d630e..c5d591f 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -26,12 +26,13 @@
 import java.nio.ByteBuffer;
 
 /**
- * Handle a HELO chunk.
+ * Handle "hello" messages and feature discovery.
  */
 public class DdmHandleHello extends ChunkHandler {
 
     public static final int CHUNK_HELO = type("HELO");
     public static final int CHUNK_WAIT = type("WAIT");
+    public static final int CHUNK_FEAT = type("FEAT");
 
     private static DdmHandleHello mInstance = new DdmHandleHello();
 
@@ -44,6 +45,7 @@
      */
     public static void register() {
         DdmServer.registerHandler(CHUNK_HELO, mInstance);
+        DdmServer.registerHandler(CHUNK_FEAT, mInstance);
     }
 
     /**
@@ -73,12 +75,27 @@
     }
 
     /**
-     * Handle a chunk of data.  We're only registered for "HELO".
+     * Handle a chunk of data.
      */
     public Chunk handleChunk(Chunk request) {
         if (Config.LOGV)
-            Log.v("ddm-hello", "Handling " + name(request.type) + " chunk");
+            Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
+        int type = request.type;
 
+        if (type == CHUNK_HELO) {
+            return handleHELO(request);
+        } else if (type == CHUNK_FEAT) {
+            return handleFEAT(request);
+        } else {
+            throw new RuntimeException("Unknown packet "
+                + ChunkHandler.name(type));
+        }
+    }
+
+    /*
+     * Handle introductory packet.
+     */
+    private Chunk handleHELO(Chunk request) {
         if (false)
             return createFailChunk(123, "This is a test");
 
@@ -125,6 +142,34 @@
         return reply;
     }
 
+    /*
+     * Handle request for list of supported features.
+     */
+    private Chunk handleFEAT(Chunk request) {
+        // TODO: query the VM to ensure that support for these features
+        // is actually compiled in
+        final String[] features = {
+            "hprof-heap-dump", "method-trace-profiling"
+        };
+
+        if (Config.LOGD)
+            Log.d("ddm-heap", "Got feature list request");
+
+        int size = 4 + 4 * features.length;
+        for (int i = features.length-1; i >= 0; i--)
+            size += features[i].length() * 2;
+
+        ByteBuffer out = ByteBuffer.allocate(size);
+        out.order(ChunkHandler.CHUNK_ORDER);
+        out.putInt(features.length);
+        for (int i = features.length-1; i >= 0; i--) {
+            out.putInt(features[i].length());
+            putString(out, features[i]);
+        }
+
+        return new Chunk(CHUNK_FEAT, out);
+    }
+
     /**
      * Send up a WAIT chunk.  The only currently defined value for "reason"
      * is zero, which means "waiting for a debugger".
diff --git a/core/java/android/ddm/DdmHandleProfiling.java b/core/java/android/ddm/DdmHandleProfiling.java
new file mode 100644
index 0000000..beed505
--- /dev/null
+++ b/core/java/android/ddm/DdmHandleProfiling.java
@@ -0,0 +1,137 @@
+/*
+ * 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.ddm;
+
+import org.apache.harmony.dalvik.ddmc.Chunk;
+import org.apache.harmony.dalvik.ddmc.ChunkHandler;
+import org.apache.harmony.dalvik.ddmc.DdmServer;
+import android.os.Debug;
+import android.util.Config;
+import android.util.Log;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Handle profiling requests.
+ */
+public class DdmHandleProfiling extends ChunkHandler {
+
+    public static final int CHUNK_MPRS = type("MPRS");
+    public static final int CHUNK_MPRE = type("MPRE");
+    public static final int CHUNK_MPRQ = type("MPRQ");
+
+    private static DdmHandleProfiling mInstance = new DdmHandleProfiling();
+
+
+    /* singleton, do not instantiate */
+    private DdmHandleProfiling() {}
+
+    /**
+     * Register for the messages we're interested in.
+     */
+    public static void register() {
+        DdmServer.registerHandler(CHUNK_MPRS, mInstance);
+        DdmServer.registerHandler(CHUNK_MPRE, mInstance);
+        DdmServer.registerHandler(CHUNK_MPRQ, mInstance);
+    }
+
+    /**
+     * Called when the DDM server connects.  The handler is allowed to
+     * send messages to the server.
+     */
+    public void connected() {}
+
+    /**
+     * Called when the DDM server disconnects.  Can be used to disable
+     * periodic transmissions or clean up saved state.
+     */
+    public void disconnected() {}
+
+    /**
+     * Handle a chunk of data.
+     */
+    public Chunk handleChunk(Chunk request) {
+        if (Config.LOGV)
+            Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
+        int type = request.type;
+
+        if (type == CHUNK_MPRS) {
+            return handleMPRS(request);
+        } else if (type == CHUNK_MPRE) {
+            return handleMPRE(request);
+        } else if (type == CHUNK_MPRQ) {
+            return handleMPRQ(request);
+        } else {
+            throw new RuntimeException("Unknown packet "
+                + ChunkHandler.name(type));
+        }
+    }
+
+    /*
+     * Handle a "Method PRofiling Start" request.
+     */
+    private Chunk handleMPRS(Chunk request) {
+        ByteBuffer in = wrapChunk(request);
+
+        int bufferSize = in.getInt();
+        int flags = in.getInt();
+        int len = in.getInt();
+        String fileName = getString(in, len);
+        if (Config.LOGV)
+            Log.v("ddm-heap", "Method profiling start: filename='" + fileName
+                + "', size=" + bufferSize + ", flags=" + flags);
+
+        try {
+            Debug.startMethodTracing(fileName, bufferSize, flags);
+            return null;        // empty response
+        } catch (RuntimeException re) {
+            return createFailChunk(1, re.getMessage());
+        }
+    }
+
+    /*
+     * Handle a "Method PRofiling End" request.
+     */
+    private Chunk handleMPRE(Chunk request) {
+        byte result;
+
+        try {
+            Debug.stopMethodTracing();
+            result = 0;
+        } catch (RuntimeException re) {
+            Log.w("ddm-heap", "Method profiling end failed: "
+                + re.getMessage());
+            result = 1;
+        }
+
+        /* create a non-empty reply so the handler fires on completion */
+        byte[] reply = { result };
+        return new Chunk(CHUNK_MPRE, reply, 0, reply.length);
+    }
+
+    /*
+     * Handle a "Method PRofiling Query" request.
+     */
+    private Chunk handleMPRQ(Chunk request) {
+        int result = Debug.isMethodTracingActive() ? 1 : 0;
+
+        /* create a non-empty reply so the handler fires on completion */
+        byte[] reply = { (byte) result };
+        return new Chunk(CHUNK_MPRQ, reply, 0, reply.length);
+    }
+}
+
diff --git a/core/java/android/ddm/DdmRegister.java b/core/java/android/ddm/DdmRegister.java
index b7f1ab8..debf189 100644
--- a/core/java/android/ddm/DdmRegister.java
+++ b/core/java/android/ddm/DdmRegister.java
@@ -50,6 +50,7 @@
         DdmHandleThread.register();
         DdmHandleHeap.register();
         DdmHandleNativeHeap.register();
+        DdmHandleProfiling.register();
         DdmHandleExit.register();
 
         DdmServer.registrationComplete();
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 106c920..ca579b6 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -405,8 +405,6 @@
      * @param params the Parameters to use for this Camera service
      */
     public void setParameters(Parameters params) {
-        Log.e(TAG, "setParameters()");
-        //params.dump();
         native_setParameters(params.flatten());
     }
 
@@ -416,7 +414,6 @@
     public Parameters getParameters() {
         Parameters p = new Parameters();
         String s = native_getParameters();
-        Log.e(TAG, "_getParameters: " + s);
         p.unflatten(s);
         return p;
     }
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 0c88a2e..67df23b 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -43,7 +43,7 @@
  * class by calling {@link android.content.Context#getSystemService(java.lang.String)
  * Context.getSystemService()} with an argument of {@link android.content.Context#SENSOR_SERVICE}.
  */
-public class SensorManager extends IRotationWatcher.Stub
+public class SensorManager
 {
     private static final String TAG = "SensorManager";
     private static final float[] mTempMatrix = new float[16];
@@ -475,7 +475,13 @@
                     // if it's null we're running in the system process
                     // which won't get the rotated values
                     try {
-                        sRotation = sWindowManager.watchRotation(this);
+                        sRotation = sWindowManager.watchRotation(
+                            new IRotationWatcher.Stub() {
+                                public void onRotationChanged(int rotation) {
+                                    SensorManager.this.onRotationChanged(rotation);
+                                }
+                            }
+                        );
                     } catch (RemoteException e) {
                     }
                 }
@@ -1386,7 +1392,7 @@
             }
         }
     }
-
+    
     class LmsFilter {
         private static final int SENSORS_RATE_MS = 20;
         private static final int COUNT = 12;
@@ -1454,7 +1460,7 @@
         }
     }
 
-
+    
     private static native void nativeClassInit();
 
     private static native int sensors_module_init();
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 1d939e1..1064fb6 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -117,28 +117,28 @@
                     mMobileDataState = state;
 
                     switch (state) {
-                        case DISCONNECTED:
-                            setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
-                            if (mInterfaceName != null) {
-                                NetworkUtils.resetConnections(mInterfaceName);
-                            }
-                            mInterfaceName = null;
-                            mDefaultGatewayAddr = 0;
-                            break;
-                        case CONNECTING:
-                            setDetailedState(DetailedState.CONNECTING, reason, apnName);
-                            break;
-                        case SUSPENDED:
-                            setDetailedState(DetailedState.SUSPENDED, reason, apnName);
-                            break;
-                        case CONNECTED:
-                            mInterfaceName = intent.getStringExtra(Phone.DATA_IFACE_NAME_KEY);
-                            if (mInterfaceName == null) {
-                                Log.d(TAG, "CONNECTED event did not supply interface name.");
-                            }
-                            setupDnsProperties();
-                            setDetailedState(DetailedState.CONNECTED, reason, apnName);
-                            break;
+                    case DISCONNECTED:
+                        setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
+                        if (mInterfaceName != null) {
+                            NetworkUtils.resetConnections(mInterfaceName);
+                        }
+                        mInterfaceName = null;
+                        mDefaultGatewayAddr = 0;
+                        break;
+                    case CONNECTING:
+                        setDetailedState(DetailedState.CONNECTING, reason, apnName);
+                        break;
+                    case SUSPENDED:
+                        setDetailedState(DetailedState.SUSPENDED, reason, apnName);
+                        break;
+                    case CONNECTED:
+                        mInterfaceName = intent.getStringExtra(Phone.DATA_IFACE_NAME_KEY);
+                        if (mInterfaceName == null) {
+                            Log.d(TAG, "CONNECTED event did not supply interface name.");
+                        }
+                        setupDnsProperties();
+                        setDetailedState(DetailedState.CONNECTED, reason, apnName);
+                        break;
                     }
                 }
             } else if (intent.getAction().equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
@@ -199,7 +199,7 @@
      */
     public boolean isAvailable() {
         getPhoneService(false);
-        
+
         /*
          * If the phone process has crashed in the past, we'll get a
          * RemoteException and need to re-reference the service.
@@ -214,7 +214,7 @@
                 if (retry == 0) getPhoneService(true);
             }
         }
-        
+
         return false;
     }
 
@@ -241,18 +241,28 @@
      * for this network.
      */
     public String getTcpBufferSizesPropName() {
-      String networkTypeStr = "unknown";
+        String networkTypeStr = "unknown";
         TelephonyManager tm = new TelephonyManager(mContext);
+        //TODO We have to edit the parameter for getNetworkType regarding CDMA
         switch(tm.getNetworkType()) {
-          case TelephonyManager.NETWORK_TYPE_GPRS:
+        case TelephonyManager.NETWORK_TYPE_GPRS:
             networkTypeStr = "gprs";
             break;
-          case TelephonyManager.NETWORK_TYPE_EDGE:
+        case TelephonyManager.NETWORK_TYPE_EDGE:
             networkTypeStr = "edge";
             break;
-          case TelephonyManager.NETWORK_TYPE_UMTS:
+        case TelephonyManager.NETWORK_TYPE_UMTS:
             networkTypeStr = "umts";
             break;
+        case TelephonyManager.NETWORK_TYPE_CDMA:
+            networkTypeStr = "cdma";
+            break;
+        case TelephonyManager.NETWORK_TYPE_EVDO_0:
+            networkTypeStr = "evdo";
+            break;
+        case TelephonyManager.NETWORK_TYPE_EVDO_A:
+            networkTypeStr = "evdo";
+            break;
         }
         return "net.tcp.buffersize." + networkTypeStr;
     }
@@ -281,7 +291,7 @@
                 if (retry == 0) getPhoneService(true);
             }
         }
-        
+
         Log.w(TAG, "Failed to tear down mobile data connectivity");
         return false;
     }
@@ -330,7 +340,7 @@
                     "Ignoring mobile radio request because could not acquire PhoneService");
                 break;
             }
-            
+
             try {
                 return mPhoneService.setRadio(turnOn);
             } catch (RemoteException e) {
@@ -344,9 +354,10 @@
 
     /**
      * Tells the phone sub-system that the caller wants to
-     * begin using the named feature. The only supported feature at
-     * this time is {@code Phone.FEATURE_ENABLE_MMS}, which allows an application
-     * to specify that it wants to send and/or receive MMS data.
+     * begin using the named feature. The only supported features at
+     * this time are {@code Phone.FEATURE_ENABLE_MMS}, which allows an application
+     * to specify that it wants to send and/or receive MMS data, and
+     * {@code Phone.FEATURE_ENABLE_SUPL}, which is used for Assisted GPS.
      * @param feature the name of the feature to be used
      * @param callingPid the process ID of the process that is issuing this request
      * @param callingUid the user ID of the process that is issuing this request
@@ -366,6 +377,8 @@
         if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
             mLastCallingPid = callingPid;
             return setEnableApn(Phone.APN_TYPE_MMS, true);
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+            return setEnableApn(Phone.APN_TYPE_SUPL, true);
         } else {
             return -1;
         }
@@ -386,6 +399,8 @@
     public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
         if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
             return setEnableApn(Phone.APN_TYPE_MMS, false);
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+            return setEnableApn(Phone.APN_TYPE_SUPL, false);
         } else {
             return -1;
         }
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 9f07c0a..66eefb2 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -30,6 +30,9 @@
  */
 final public class Proxy {
 
+    // Set to true to enable extra debugging.
+    static final private boolean DEBUG = false;
+
     static final public String PROXY_CHANGE_ACTION =
         "android.intent.action.PROXY_CHANGE";
 
@@ -49,7 +52,7 @@
         if (host != null) {
             int i = host.indexOf(':');
             if (i == -1) {
-                if (android.util.Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(host.length() == 0);
                 }
                 return null;
@@ -73,12 +76,12 @@
         if (host != null) {
             int i = host.indexOf(':');
             if (i == -1) {
-                if (android.util.Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(host.length() == 0);
                 }
                 return -1;
             }
-            if (android.util.Config.DEBUG) {
+            if (DEBUG) {
                 Assert.assertTrue(i < host.length());
             }
             return Integer.parseInt(host.substring(i+1));
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 17594d4..333ba73 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -80,35 +80,40 @@
      * Include only the run since the last time the device was unplugged in the stats.
      */
     public static final int STATS_UNPLUGGED = 3;
+
+    // NOTE: Update this list if you add/change any stats above.
+    // These characters are supposed to represent "total", "last", "current", 
+    // and "unplugged". They were shortened for effeciency sake.
+    private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
     
     /**
      * Bump the version on this if the checkin format changes.
      */
-    private static final int BATTERY_STATS_CHECKIN_VERSION = 3;
+    private static final int BATTERY_STATS_CHECKIN_VERSION = 5;
     
     private static final long BYTES_PER_KB = 1024;
     private static final long BYTES_PER_MB = 1048576; // 1024^2
     private static final long BYTES_PER_GB = 1073741824; //1024^3
     
-    // TODO: Update this list if you add/change any stats above.
-    private static final String[] STAT_NAMES = { "total", "last", "current", "unplugged" };
 
     private static final String APK_DATA = "apk";
-    private static final String PROCESS_DATA = "process";
-    private static final String SENSOR_DATA = "sensor";
-    private static final String WAKELOCK_DATA = "wakelock";
-    private static final String NETWORK_DATA = "network";
-    private static final String USER_ACTIVITY_DATA = "useract";
-    private static final String BATTERY_DATA = "battery";
-    private static final String WIFI_LOCK_DATA = "wifilock";
-    private static final String MISC_DATA = "misc";
-    private static final String SCREEN_BRIGHTNESS_DATA = "brightness";
-    private static final String SIGNAL_STRENGTH_TIME_DATA = "sigtime";
-    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sigcnt";
-    private static final String DATA_CONNECTION_TIME_DATA = "dconntime";
-    private static final String DATA_CONNECTION_COUNT_DATA = "dconncnt";
+    private static final String PROCESS_DATA = "pr";
+    private static final String SENSOR_DATA = "sr";
+    private static final String WAKELOCK_DATA = "wl";
+    private static final String KERNEL_WAKELOCK_DATA = "kwl";
+    private static final String NETWORK_DATA = "nt";
+    private static final String USER_ACTIVITY_DATA = "ua";
+    private static final String BATTERY_DATA = "bt";
+    private static final String BATTERY_LEVEL_DATA = "lv";
+    private static final String WIFI_LOCK_DATA = "wfl";
+    private static final String MISC_DATA = "m";
+    private static final String SCREEN_BRIGHTNESS_DATA = "br";
+    private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
+    private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
+    private static final String DATA_CONNECTION_TIME_DATA = "dct";
+    private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
 
-    private final StringBuilder mFormatBuilder = new StringBuilder(8);
+    private final StringBuilder mFormatBuilder = new StringBuilder(32);
     private final Formatter mFormatter = new Formatter(mFormatBuilder);
 
     /**
@@ -122,7 +127,7 @@
          *
          * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
          */
-        public abstract int getCount(int which);
+        public abstract int getCountLocked(int which);
 
         /**
          * Temporary for debugging.
@@ -141,7 +146,7 @@
          *
          * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
          */
-        public abstract int getCount(int which);
+        public abstract int getCountLocked(int which);
 
         /**
          * Returns the total time in microseconds associated with this Timer for the
@@ -151,7 +156,7 @@
          * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
          * @return a time in microseconds
          */
-        public abstract long getTotalTime(long batteryRealtime, int which);
+        public abstract long getTotalTimeLocked(long batteryRealtime, int which);
         
         /**
          * Temporary for debugging.
@@ -472,15 +477,16 @@
     public abstract long getBatteryRealtime(long curTime);
     
     /**
-     * Returns the battery percentage level at the last time the device was unplugged from power, 
-     * or the last time it was booted while unplugged.
+     * Returns the battery percentage level at the last time the device was unplugged from power, or
+     * the last time it booted on battery power. 
      */
-    public abstract int getUnpluggedStartLevel();
+    public abstract int getDischargeStartLevel();
     
     /**
-     * Returns the battery percentage level at the last time the device was plugged into power.
+     * Returns the current battery percentage level if we are in a discharge cycle, otherwise
+     * returns the level at the last plug event.
      */
-    public abstract int getPluggedStartLevel();
+    public abstract int getDischargeCurrentLevel();
 
     /**
      * Returns the total, last, or current battery uptime in microseconds.
@@ -513,8 +519,10 @@
      * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
      */
     public abstract long computeRealtime(long curTime, int which);
+    
+    public abstract Map<String, ? extends Timer> getKernelWakelockStats();
 
-    private final static void formatTime(StringBuilder out, long seconds) {
+    private final static void formatTimeRaw(StringBuilder out, long seconds) {
         long days = seconds / (60 * 60 * 24);
         if (days != 0) {
             out.append(days);
@@ -542,22 +550,18 @@
         }
     }
 
-    private final static String formatTime(long time) {
+    private final static void formatTime(StringBuilder sb, long time) {
         long sec = time / 100;
-        StringBuilder sb = new StringBuilder();
-        formatTime(sb, sec);
+        formatTimeRaw(sb, sec);
         sb.append((time - (sec * 100)) * 10);
         sb.append("ms ");
-        return sb.toString();
     }
 
-    private final static String formatTimeMs(long time) {
+    private final static void formatTimeMs(StringBuilder sb, long time) {
         long sec = time / 1000;
-        StringBuilder sb = new StringBuilder();
-        formatTime(sb, sec);
+        formatTimeRaw(sb, sec);
         sb.append(time - (sec * 1000));
         sb.append("ms ");
-        return sb.toString();
     }
 
     private final String formatRatioLocked(long num, long den) {
@@ -602,14 +606,14 @@
         
         if (timer != null) {
             // Convert from microseconds to milliseconds with rounding
-            long totalTimeMicros = timer.getTotalTime(batteryRealtime, which);
+            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
             long totalTimeMillis = (totalTimeMicros + 500) / 1000;
             
-            int count = timer.getCount(which);
+            int count = timer.getCountLocked(which);
             if (totalTimeMillis != 0) {
                 sb.append(linePrefix);
-                sb.append(formatTimeMs(totalTimeMillis));
-                sb.append(name);
+                formatTimeMs(sb, totalTimeMillis);
+                if (name != null) sb.append(name);
                 sb.append(' ');
                 sb.append('(');
                 sb.append(count);
@@ -632,18 +636,17 @@
      * @return the line prefix
      */
     private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
-        String name, int which, String linePrefix) {
+            String name, int which, String linePrefix) {
         long totalTimeMicros = 0;
         int count = 0;
         if (timer != null) {
-            totalTimeMicros = timer.getTotalTime(now, which);
-            count = timer.getCount(which); 
+            totalTimeMicros = timer.getTotalTimeLocked(now, which);
+            count = timer.getCountLocked(which); 
         }
         sb.append(linePrefix);
         sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
         sb.append(',');
-        sb.append(name);
-        sb.append(',');
+        sb.append(name != null ? name + "," : "");
         sb.append(count);
         return ",";
     }
@@ -725,12 +728,12 @@
                     
                     Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
                     if (fullWakeTimer != null) {
-                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTime(batteryRealtime, which);
+                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
                     }
 
                     Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
                     if (partialWakeTimer != null) {
-                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTime(
+                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
                             batteryRealtime, which);
                     }
                 }
@@ -774,8 +777,19 @@
         dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
         
         if (which == STATS_UNPLUGGED) {
-            dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(), 
-                    getPluggedStartLevel());
+            dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(), 
+                    getDischargeCurrentLevel());
+        }
+        
+        Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+        if (kernelWakelocks.size() > 0) {
+            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+                sb.setLength(0);
+                printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
+
+                dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), 
+                        sb.toString());
+            }
         }
         
         for (int iu = 0; iu < NU; iu++) {
@@ -816,12 +830,12 @@
                     Uid.Wakelock wl = ent.getValue();
                     String linePrefix = "";
                     sb.setLength(0);
-                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
-                            "full", which, linePrefix);
-                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
-                            "partial", which, linePrefix);
-                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
-                            "window", which, linePrefix);
+                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), 
+                            batteryRealtime, "f", which, linePrefix);
+                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), 
+                            batteryRealtime, "p", which, linePrefix);
+                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), 
+                            batteryRealtime, "w", which, linePrefix);
                     
                     // Only log if we had at lease one wakelock...
                     if (sb.length() > 0) {
@@ -839,8 +853,8 @@
                     Timer timer = se.getSensorTime();
                     if (timer != null) {
                         // Convert from microseconds to milliseconds with rounding
-                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
-                        int count = timer.getCount(which);
+                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
+                        int count = timer.getCountLocked(which);
                         if (totalTime != 0) {
                             dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
                         }
@@ -898,7 +912,7 @@
     }
 
     @SuppressWarnings("unused")
-    private final void dumpLocked(Printer pw, String prefix, int which) {
+    private final void dumpLocked(PrintWriter pw, String prefix, int which) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
@@ -914,33 +928,41 @@
         SparseArray<? extends Uid> uidStats = getUidStats();
         final int NU = uidStats.size();
 
-        pw.println(prefix
-                + "  Time on battery: "
-                + formatTimeMs(whichBatteryRealtime / 1000) + "("
-                + formatRatioLocked(whichBatteryRealtime, totalRealtime)
-                + ") realtime, "
-                + formatTimeMs(whichBatteryUptime / 1000)
-                + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime)
-                + ") uptime");
-        pw.println(prefix
-                + "  Total run time: "
-                + formatTimeMs(totalRealtime / 1000)
-                + "realtime, "
-                + formatTimeMs(totalUptime / 1000)
-                + "uptime, ");
+        sb.setLength(0);
+        sb.append(prefix);
+                sb.append("  Time on battery: ");
+                formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("(");
+                sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime));
+                sb.append(") realtime, ");
+                formatTimeMs(sb, whichBatteryUptime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime));
+                sb.append(") uptime");
+        pw.println(sb.toString());
+        sb.setLength(0);
+        sb.append(prefix);
+                sb.append("  Total run time: ");
+                formatTimeMs(sb, totalRealtime / 1000);
+                sb.append("realtime, ");
+                formatTimeMs(sb, totalUptime / 1000);
+                sb.append("uptime, ");
+        pw.println(sb.toString());
         
         final long screenOnTime = getScreenOnTime(batteryRealtime, which);
         final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
         final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
         final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
         final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
-        pw.println(prefix
-                + "  Screen on: " + formatTimeMs(screenOnTime / 1000)
-                + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime)
-                + "), Input events: " + getInputEventCount(which)
-                + ", Active phone call: " + formatTimeMs(phoneOnTime / 1000)
-                + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")");
         sb.setLength(0);
+        sb.append(prefix);
+                sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
+                sb.append("), Input events: "); sb.append(getInputEventCount(which));
+                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
+                sb.append(")");
+        pw.println(sb.toString());
+        sb.setLength(0);
+        sb.append(prefix);
         sb.append("  Screen brightnesses: ");
         boolean didOne = false;
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
@@ -952,7 +974,7 @@
             didOne = true;
             sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
             sb.append(" ");
-            sb.append(formatTimeMs(time/1000));
+            formatTimeMs(sb, time/1000);
             sb.append("(");
             sb.append(formatRatioLocked(time, screenOnTime));
             sb.append(")");
@@ -966,6 +988,26 @@
         long fullWakeLockTimeTotalMicros = 0;
         long partialWakeLockTimeTotalMicros = 0;
         
+        Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+        if (kernelWakelocks.size() > 0) {
+            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+                
+                String linePrefix = ": ";
+                sb.setLength(0);
+                sb.append(prefix);
+                sb.append("  Kernel Wake lock ");
+                sb.append(ent.getKey());
+                linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which, 
+                        linePrefix);
+                if (!linePrefix.equals(": ")) {
+                    sb.append(" realtime");
+                } else {
+                    sb.append(": (nothing executed)");
+                }
+                pw.println(sb.toString());
+            }
+        }
+    
         for (int iu = 0; iu < NU; iu++) {
             Uid u = uidStats.valueAt(iu);
             rxTotal += u.getTcpBytesReceived(which);
@@ -979,29 +1021,32 @@
                     
                     Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
                     if (fullWakeTimer != null) {
-                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTime(
+                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
                                 batteryRealtime, which);
                     }
 
                     Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
                     if (partialWakeTimer != null) {
-                        partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTime(
+                        partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
                                 batteryRealtime, which);
                     }
                 }
             }
         }
         
-        pw.println(prefix
-                + "  Total received: " + formatBytesLocked(rxTotal)
-                + ", Total sent: " + formatBytesLocked(txTotal));
-        pw.println(prefix
-                + "  Total full wakelock time: " + formatTimeMs(
-                        (fullWakeLockTimeTotalMicros + 500) / 1000)
-                + ", Total partial waklock time: " + formatTimeMs(
-                        (partialWakeLockTimeTotalMicros + 500) / 1000));
+        pw.print(prefix);
+                pw.print("  Total received: "); pw.print(formatBytesLocked(rxTotal));
+                pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal));
+        sb.setLength(0);
+        sb.append(prefix);
+                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
+                        (fullWakeLockTimeTotalMicros + 500) / 1000);
+                sb.append(", Total partial waklock time: "); formatTimeMs(sb,
+                        (partialWakeLockTimeTotalMicros + 500) / 1000);
+        pw.println(sb.toString());
         
         sb.setLength(0);
+        sb.append(prefix);
         sb.append("  Signal levels: ");
         didOne = false;
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -1013,7 +1058,7 @@
             didOne = true;
             sb.append(SIGNAL_STRENGTH_NAMES[i]);
             sb.append(" ");
-            sb.append(formatTimeMs(time/1000));
+            formatTimeMs(sb, time/1000);
             sb.append("(");
             sb.append(formatRatioLocked(time, whichBatteryRealtime));
             sb.append(") ");
@@ -1024,6 +1069,7 @@
         pw.println(sb.toString());
         
         sb.setLength(0);
+        sb.append(prefix);
         sb.append("  Radio types: ");
         didOne = false;
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
@@ -1035,7 +1081,7 @@
             didOne = true;
             sb.append(DATA_CONNECTION_NAMES[i]);
             sb.append(" ");
-            sb.append(formatTimeMs(time/1000));
+            formatTimeMs(sb, time/1000);
             sb.append("(");
             sb.append(formatRatioLocked(time, whichBatteryRealtime));
             sb.append(") ");
@@ -1045,27 +1091,32 @@
         if (!didOne) sb.append("No activity");
         pw.println(sb.toString());
         
-        pw.println(prefix
-                + "  Wifi on: " + formatTimeMs(wifiOnTime / 1000)
-                + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime)
-                + "), Wifi running: " + formatTimeMs(wifiRunningTime / 1000)
-                + "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime)
-                + "), Bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000)
-                + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")");
+        sb.setLength(0);
+        sb.append(prefix);
+                sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime));
+                sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime));
+                sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
+                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
+                sb.append(")");
+        pw.println(sb.toString());
         
         pw.println(" ");
 
         if (which == STATS_UNPLUGGED) {
             if (getIsOnBattery()) {
-                pw.println(prefix + "  Device is currently unplugged");
-                pw.println(prefix + "    Discharge cycle start level: " + 
-                        getUnpluggedStartLevel());
+                pw.print(prefix); pw.println("  Device is currently unplugged");
+                pw.print(prefix); pw.print("    Discharge cycle start level: "); 
+                        pw.println(getDischargeStartLevel());
+                pw.print(prefix); pw.print("    Discharge cycle current level: ");
+                        pw.println(getDischargeCurrentLevel());
             } else {
-                pw.println(prefix + "  Device is currently plugged into power");
-                pw.println(prefix + "    Last discharge cycle start level: " + 
-                        getUnpluggedStartLevel());
-                pw.println(prefix + "    Last discharge cycle end level: " + 
-                        getPluggedStartLevel());
+                pw.print(prefix); pw.println("  Device is currently plugged into power");
+                pw.print(prefix); pw.print("    Last discharge cycle start level: "); 
+                        pw.println(getDischargeStartLevel());
+                pw.print(prefix); pw.print("    Last discharge cycle end level: "); 
+                        pw.println(getDischargeCurrentLevel());
             }
             pw.println(" ");
         }
@@ -1084,8 +1135,9 @@
             long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
             
             if (tcpReceived != 0 || tcpSent != 0) {
-                pw.println(prefix + "    Network: " + formatBytesLocked(tcpReceived) + " received, "
-                        + formatBytesLocked(tcpSent) + " sent");
+                pw.print(prefix); pw.print("    Network: ");
+                        pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, ");
+                        pw.print(formatBytesLocked(tcpSent)); pw.println(" sent");
             }
             
             if (u.hasUserActivity()) {
@@ -1112,18 +1164,20 @@
             
             if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
                     || wifiTurnedOnTime != 0) {
-                pw.println(prefix + "    Turned Wifi On Time: " 
-                        + formatTimeMs(wifiTurnedOnTime / 1000) 
-                        + "(" + formatRatioLocked(wifiTurnedOnTime, 
-                                whichBatteryRealtime)+ ")");
-                pw.println(prefix + "    Full Wifi Lock Time: " 
-                        + formatTimeMs(fullWifiLockOnTime / 1000) 
-                        + "(" + formatRatioLocked(fullWifiLockOnTime, 
-                                whichBatteryRealtime)+ ")");
-                pw.println(prefix + "    Scan Wifi Lock Time: " 
-                        + formatTimeMs(scanWifiLockOnTime / 1000)
-                        + "(" + formatRatioLocked(scanWifiLockOnTime, 
-                                whichBatteryRealtime)+ ")");
+                sb.setLength(0);
+                sb.append(prefix); sb.append("    Turned Wifi On: "); 
+                        formatTimeMs(sb, wifiTurnedOnTime / 1000); 
+                        sb.append("("); sb.append(formatRatioLocked(wifiTurnedOnTime, 
+                                whichBatteryRealtime)); sb.append(")\n");
+                sb.append(prefix); sb.append("    Full Wifi Lock: "); 
+                        formatTimeMs(sb, fullWifiLockOnTime / 1000); 
+                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime, 
+                                whichBatteryRealtime)); sb.append(")\n");
+                sb.append(prefix); sb.append("    Scan Wifi Lock: "); 
+                        formatTimeMs(sb, scanWifiLockOnTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime, 
+                                whichBatteryRealtime)); sb.append(")");
+                pw.println(sb.toString());
             }
 
             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
@@ -1172,11 +1226,12 @@
                     Timer timer = se.getSensorTime();
                     if (timer != null) {
                         // Convert from microseconds to milliseconds with rounding
-                        long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
-                        int count = timer.getCount(which);
+                        long totalTime = (timer.getTotalTimeLocked(
+                                batteryRealtime, which) + 500) / 1000;
+                        int count = timer.getCountLocked(which);
                         //timer.logState();
                         if (totalTime != 0) {
-                            sb.append(formatTimeMs(totalTime));
+                            formatTimeMs(sb, totalTime);
                             sb.append("realtime (");
                             sb.append(count);
                             sb.append(" times)");
@@ -1206,10 +1261,15 @@
                     starts = ps.getStarts(which);
 
                     if (userTime != 0 || systemTime != 0 || starts != 0) {
-                        pw.println(prefix + "    Proc " + ent.getKey() + ":");
-                        pw.println(prefix + "      CPU: " + formatTime(userTime) + "user + "
-                                + formatTime(systemTime) + "kernel");
-                        pw.println(prefix + "      " + starts + " process starts");
+                        sb.setLength(0);
+                        sb.append(prefix); sb.append("    Proc ");
+                                sb.append(ent.getKey()); sb.append(":\n");
+                        sb.append(prefix); sb.append("      CPU: ");
+                                formatTime(sb, userTime); sb.append("usr + ");
+                                formatTime(sb, systemTime); sb.append("krn\n");
+                        sb.append(prefix); sb.append("      "); sb.append(starts);
+                                sb.append(" proc starts");
+                        pw.println(sb.toString());
                         uidActivity = true;
                     }
                 }
@@ -1219,12 +1279,13 @@
             if (packageStats.size() > 0) {
                 for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
                     : packageStats.entrySet()) {
-                    pw.println(prefix + "    Apk " + ent.getKey() + ":");
+                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
                     boolean apkActivity = false;
                     Uid.Pkg ps = ent.getValue();
                     int wakeups = ps.getWakeups(which);
                     if (wakeups != 0) {
-                        pw.println(prefix + "      " + wakeups + " wakeup alarms");
+                        pw.print(prefix); pw.print("      ");
+                                pw.print(wakeups); pw.println(" wakeup alarms");
                         apkActivity = true;
                     }
                     Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
@@ -1236,24 +1297,28 @@
                             int starts = ss.getStarts(which);
                             int launches = ss.getLaunches(which);
                             if (startTime != 0 || starts != 0 || launches != 0) {
-                                pw.println(prefix + "      Service " + sent.getKey() + ":");
-                                pw.println(prefix + "        Created for: "
-                                        + formatTimeMs(startTime / 1000)
-                                        + " uptime");
-                                pw.println(prefix + "        Starts: " + starts
-                                        + ", launches: " + launches);
+                                sb.setLength(0);
+                                sb.append(prefix); sb.append("      Service ");
+                                        sb.append(sent.getKey()); sb.append(":\n");
+                                sb.append(prefix); sb.append("        Created for: ");
+                                        formatTimeMs(sb, startTime / 1000);
+                                        sb.append(" uptime\n");
+                                sb.append(prefix); sb.append("        Starts: ");
+                                        sb.append(starts);
+                                        sb.append(", launches: "); sb.append(launches);
+                                pw.println(sb.toString());
                                 apkActivity = true;
                             }
                         }
                     }
                     if (!apkActivity) {
-                        pw.println(prefix + "      (nothing executed)");
+                        pw.print(prefix); pw.println("      (nothing executed)");
                     }
                     uidActivity = true;
                 }
             }
             if (!uidActivity) {
-                pw.println(prefix + "    (nothing executed)");
+                pw.print(prefix); pw.println("    (nothing executed)");
             }
         }
     }
@@ -1264,7 +1329,7 @@
      * @param pw a Printer to receive the dump output.
      */
     @SuppressWarnings("unused")
-    public void dumpLocked(Printer pw) {
+    public void dumpLocked(PrintWriter pw) {
         pw.println("Total Statistics (Current and Historic):");
         pw.println("  System starts: " + getStartCount()
                 + ", currently on battery: " + getIsOnBattery());
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 950bb09..5ea5aae 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -364,6 +364,14 @@
     }
 
     /**
+     * Determine whether method tracing is currently active.
+     * @hide
+     */
+    public static boolean isMethodTracingActive() {
+        return VMDebug.isMethodTracingActive();
+    }
+
+    /**
      * Stop method tracing.
      */
     public static void stopMethodTracing() {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index cd86fbe..30acef9 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -176,6 +176,26 @@
      */
     public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1;
 
+    /**
+     * Default thread group - gets a 'normal' share of the CPU
+     * @hide
+     */
+    public static final int THREAD_GROUP_DEFAULT = 0;
+
+    /**
+     * Background non-interactive thread group - All threads in
+     * this group are scheduled with a reduced share of the CPU.
+     * @hide
+     */
+    public static final int THREAD_GROUP_BG_NONINTERACTIVE = 1;
+
+    /**
+     * Foreground 'boost' thread group - All threads in
+     * this group are scheduled with an increased share of the CPU
+     * @hide
+     **/
+    public static final int THREAD_GROUP_FG_BOOST = 2;
+
     public static final int SIGNAL_QUIT = 3;
     public static final int SIGNAL_KILL = 9;
     public static final int SIGNAL_USR1 = 10;
@@ -569,6 +589,21 @@
      */
     public static final native void setThreadPriority(int tid, int priority)
             throws IllegalArgumentException, SecurityException;
+
+    /**
+     * Sets the scheduling group for a thread.
+     * @hide
+     * @param tid The indentifier of the thread/process to change.
+     * @param group The target group for this thread/process.
+     * 
+     * @throws IllegalArgumentException Throws IllegalArgumentException if
+     * <var>tid</var> does not exist.
+     * @throws SecurityException Throws SecurityException if your process does
+     * not have permission to modify the given thread, or to use the given
+     * priority.
+     */
+    public static final native void setThreadGroup(int tid, int group)
+            throws IllegalArgumentException, SecurityException;
     
     /**
      * Set the priority of the calling thread, based on Linux priorities.  See
@@ -680,6 +715,8 @@
     /** @hide */
     public static final int PROC_SPACE_TERM = (int)' ';
     /** @hide */
+    public static final int PROC_TAB_TERM = (int)'\t';
+    /** @hide */
     public static final int PROC_COMBINE = 0x100;
     /** @hide */
     public static final int PROC_PARENS = 0x200;
@@ -693,6 +730,10 @@
     /** @hide */
     public static final native boolean readProcFile(String file, int[] format,
             String[] outStrings, long[] outLongs, float[] outFloats);
+    
+    /** @hide */
+    public static final native boolean parseProcLine(byte[] buffer, int startIndex, 
+            int endIndex, int[] format, String[] outStrings, long[] outLongs, float[] outFloats);
 
     /**
      * Gets the total Pss value for a given process, in bytes.
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index a255438..fc39573 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -92,6 +92,7 @@
     private boolean mPersistent = true;
     private String mDependencyKey;
     private Object mDefaultValue;
+    private boolean mDependencyMet = true;
     
     /**
      * @see #setShouldDisableView(boolean)
@@ -594,7 +595,7 @@
      * @return True if this Preference is enabled, false otherwise.
      */
     public boolean isEnabled() {
-        return mEnabled;
+        return mEnabled && mDependencyMet;
     }
 
     /**
@@ -1096,7 +1097,14 @@
      * @param disableDependent Set true to disable this Preference.
      */
     public void onDependencyChanged(Preference dependency, boolean disableDependent) {
-        setEnabled(!disableDependent);
+        if (mDependencyMet == disableDependent) {
+            mDependencyMet = !disableDependent;
+
+            // Enabled state can change dependent preferences' states, so notify
+            notifyDependencyChange(shouldDisableDependents());
+
+            notifyChanged();
+        }
     }
     
     /**
diff --git a/core/java/android/provider/Applications.java b/core/java/android/provider/Applications.java
new file mode 100644
index 0000000..0b0ce58
--- /dev/null
+++ b/core/java/android/provider/Applications.java
@@ -0,0 +1,82 @@
+/*
+ * 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.provider;
+
+import android.app.SearchManager;
+import android.net.Uri;
+import android.widget.SimpleCursorAdapter;
+
+/**
+ * <p>The Applications provider gives information about installed applications.</p>
+ * 
+ * <p>This provider provides the following columns:
+ * 
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ *
+ *     <thead>
+ *     <tr><th>Column Name</th> <th>Description</th> </tr>
+ *     </thead>
+ *
+ * <tbody>
+ * <tr><th>{@link SearchManager#SUGGEST_COLUMN_TEXT_1}</th>
+ *     <td>The application name.</td>
+ * </tr>
+ * 
+ * <tr><th>{@link SearchManager#SUGGEST_COLUMN_INTENT_COMPONENT}</th>
+ *     <td>The component to be used when forming the intent.</td>
+ * </tr>
+ * 
+ * <tr><th>{@link SearchManager#SUGGEST_COLUMN_ICON_1}</th>
+ *     <td>The application's icon resource id, prepended by its package name and
+ *         separated by a colon, e.g., "com.android.alarmclock:2130837524". The
+ *         package name is required for an activity interpreting this value to
+ *         be able to correctly access the icon drawable, for example, in an override of
+ *         {@link SimpleCursorAdapter#setViewImage(android.widget.ImageView, String)}.</td>
+ * </tr>
+ * 
+ * <tr><th>{@link SearchManager#SUGGEST_COLUMN_ICON_2}</th>
+ *     <td><i>Unused - column provided to conform to the {@link SearchManager} stipulation
+ *            that all providers provide either both or neither of
+ *            {@link SearchManager#SUGGEST_COLUMN_ICON_1} and
+ *            {@link SearchManager#SUGGEST_COLUMN_ICON_2}.</td>
+ * </tr>
+ * 
+ * @hide pending API council approval - should be unhidden at the same time as
+ *       {@link SearchManager#SUGGEST_COLUMN_INTENT_COMPONENT}
+ */
+public class Applications {
+    private static final String TAG = "Applications";
+
+    /**
+     * The content authority for this provider.
+     *
+     * @hide
+     */
+    public static final String AUTHORITY = "applications";
+
+    /**
+     * The content:// style URL for this provider
+     *
+     * @hide
+     */
+    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
+
+    /**
+     * no public constructor since this is a utility class
+     */
+    private Applications() {}
+}
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
index a87f5fa..3c23db0 100644
--- a/core/java/android/provider/Checkin.java
+++ b/core/java/android/provider/Checkin.java
@@ -132,6 +132,7 @@
             BROWSER_SNAP_CENTER,
             BROWSER_TEXT_SIZE_CHANGE,
             BROWSER_ZOOM_OVERVIEW,
+
             CRASHES_REPORTED,
             CRASHES_TRUNCATED,
             ELAPSED_REALTIME_SEC,
@@ -181,6 +182,9 @@
             MARKET_REASON_PARSE_MANIFEST_EMPTY,
             MARKET_REASON_UNKNOWN,
             MARKET_STALE_INSTALL_ATTEMPT,
+            PHONE_CDMA_REGISTERED,
+            PHONE_CDMA_DATA_ATTEMPTED,
+            PHONE_CDMA_DATA_CONNECTED,
         }
     }
 
@@ -347,3 +351,6 @@
         }
     }
 }
+
+
+
diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java
index cc03968..c4b29ae 100644
--- a/core/java/android/provider/Gmail.java
+++ b/core/java/android/provider/Gmail.java
@@ -38,7 +38,6 @@
 import android.text.TextUtils.SimpleStringSplitter;
 import android.text.style.CharacterStyle;
 import android.text.util.Regex;
-import android.util.Config;
 import android.util.Log;
 
 import java.io.UnsupportedEncodingException;
@@ -61,6 +60,9 @@
  * @hide
  */
 public final class Gmail {
+    // Set to true to enable extra debugging.
+    private static final boolean DEBUG = false;
+
     public static final String GMAIL_AUTH_SERVICE = "mail";
     // These constants come from google3/java/com/google/caribou/backend/MailLabel.java.
     public static final String LABEL_SENT = "^f";
@@ -1195,7 +1197,7 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            if (Config.DEBUG) {
+            if (DEBUG) {
                 Log.d(TAG, "MailCursor is notifying " + mObservers.size() + " observers");
             }
             for (MailCursorObserver o: mObservers) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c035be2..4dd6524 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1280,7 +1280,7 @@
         // Settings moved to Settings.Secure
 
         /**
-         * @deprecated Use {@link android.provider.Settings.Secure#LOCATION_PROVIDERS_ALLOWED}
+         * @deprecated Use {@link android.provider.Settings.Secure#ADB_ENABLED}
          * instead
          */
         @Deprecated
@@ -2034,6 +2034,110 @@
          * ConnectivityManager for more info.
          */
         public static final String BACKGROUND_DATA = "background_data";
+
+        /**
+         * The CDMA roaming mode 0 = Home Networks, CDMA default
+         *                       1 = Roaming on Affiliated networks
+         *                       2 = Roaming on any networks
+         * @hide
+         */
+        public static final String CDMA_ROAMING_MODE = "roaming_settings";
+
+        /**
+         * The CDMA subscription mode 0 = RUIM/SIM (default)
+         *                                1 = NV
+         * @hide
+         */
+        public static final String CDMA_SUBSCRIPTION_MODE = "subscription_mode";
+
+        /**
+         * represents current active phone class
+         * 1 = GSM-Phone, 0 = CDMA-Phone
+         * @hide
+         */
+        public static final String CURRENT_ACTIVE_PHONE = "current_active_phone";
+
+        /**
+         * The preferred network mode 7 = Global, CDMA default
+         *                            4 = CDMA only
+         *                            3 = GSM/UMTS only
+         * @hide
+         */
+        public static final String PREFERRED_NETWORK_MODE =
+                "preferred_network_mode";
+
+        /**
+         * CDMA Cell Broadcast SMS
+         *                            0 = CDMA Cell Broadcast SMS disabled
+         *                            1 = CDMA Cell Broadcast SMS enabled
+         * @hide
+         */
+        public static final String CDMA_CELL_BROADCAST_SMS =
+                "cdma_cell_broadcast_sms";
+
+        /**
+         * The cdma subscription 0 = Subscription from RUIM, when available
+         *                       1 = Subscription from NV
+         * @hide
+         */
+        public static final String PREFERRED_CDMA_SUBSCRIPTION =
+                "preferred_cdma_subscription";
+
+        /**
+         * Whether the enhanced voice privacy mode is enabled.
+         * 0 = normal voice privacy
+         * 1 = enhanced voice privacy
+         * @hide
+         */
+        public static final String ENHANCED_VOICE_PRIVACY_ENABLED = "enhanced_voice_privacy_enabled";
+
+        /**
+         * Whether the TTY mode mode is enabled.
+         * 0 = disabled
+         * 1 = enabled
+         * @hide
+         */
+        public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
+
+        /**
+         * Helper method for determining if a location provider is enabled.
+         * @param cr the content resolver to use
+         * @param provider the location provider to query
+         * @return true if the provider is enabled
+         *
+         * @hide
+         */
+        public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
+            String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
+            if (allowedProviders != null) {
+                return (allowedProviders.equals(provider) ||
+                        allowedProviders.contains("," + provider + ",") ||
+                        allowedProviders.startsWith(provider + ",") ||
+                        allowedProviders.endsWith("," + provider));
+            }
+            return false;           
+        }
+
+        /**
+         * Thread-safe method for enabling or disabling a single location provider.
+         * @param cr the content resolver to use
+         * @param provider the location provider to enable or disable
+         * @param enabled true if the provider should be enabled
+         *
+         * @hide
+         */
+        public static final void setLocationProviderEnabled(ContentResolver cr,
+                String provider, boolean enabled) {
+            // to ensure thread safety, we write the provider name with a '+' or '-'
+            // and let the SettingsProvider handle it rather than reading and modifying
+            // the list of enabled providers.
+            if (enabled) {
+                provider = "+" + provider;
+            } else {
+                provider = "-" + provider;
+            }
+            putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
+        }
     }
     
     /**
@@ -2324,6 +2428,12 @@
         public static final String GMAIL_BUFFER_SERVER_RESPONSE = "gmail_buffer_server_response";
 
         /**
+         * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be
+         * an integer where non-zero means true. Defaults to 1.
+         */
+        public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op";
+
+        /**
          * Hostname of the GTalk server.
          */
         public static final String GTALK_SERVICE_HOSTNAME = "gtalk_hostname";
@@ -3112,13 +3222,13 @@
             throw new RuntimeException("this should never happen");
         }
 
-        String imei = TelephonyManager.getDefault().getDeviceId();
-        if (TextUtils.isEmpty(imei)) {
+        String deviceId = TelephonyManager.getDefault().getDeviceId();
+        if (TextUtils.isEmpty(deviceId)) {
             return "";
         }
 
-        byte[] hashedImei = digest.digest(imei.getBytes());
-        String id = new String(Base64.encodeBase64(hashedImei), 0, 12);
+        byte[] hashedDeviceId = digest.digest(deviceId.getBytes());
+        String id = new String(Base64.encodeBase64(hashedDeviceId), 0, 12);
         id = id.replaceAll("/", "_");
         sJidResource = JID_RESOURCE_PREFIX + id;
         return sJidResource;
@@ -3137,3 +3247,4 @@
         return "android-" + Long.toHexString(androidId);
     }
 }
+
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 61ab228..a4145c4 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -26,7 +26,7 @@
 import android.content.Intent;
 import android.database.Cursor;
 import android.net.Uri;
-import android.telephony.gsm.SmsMessage;
+import android.telephony.SmsMessage;
 import android.text.TextUtils;
 import android.text.util.Regex;
 import android.util.Config;
@@ -47,6 +47,10 @@
     private static final boolean DEBUG = false;
     private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
 
+    // Constructor
+    public Telephony() {
+    }
+
     /**
      * Base columns for tables that contain text based SMSs.
      */
@@ -1601,3 +1605,5 @@
 }
 
 
+
+
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 11c297c..8cc229b 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -111,57 +111,27 @@
         return mPasskeyAgentRequestData;
     }
 
-    private synchronized boolean waitForAndDispatchEvent(int timeout_ms) {
-        return waitForAndDispatchEventNative(timeout_ms);
-    }
-    private native boolean waitForAndDispatchEventNative(int timeout_ms);
+    private native void startEventLoopNative();
+    private native void stopEventLoopNative();
+    private native boolean isEventLoopRunningNative();
 
-    /* package */ synchronized void start() {
+    /* package */ void start() {
 
-        if (mThread != null) {
-            // Already running.
-            return;
-        }
-        mThread = new Thread("Bluetooth Event Loop") {
-                @Override
-                public void run() {
-                    try {
-                        if (setUpEventLoopNative()) {
-                            mStarted = true;
-                            while (!mInterrupted) {
-                                waitForAndDispatchEvent(0);
-                                sleep(500);
-                            }
-                        }
-                        // tear down even in the error case to clean
-                        // up anything we started to setup
-                        tearDownEventLoopNative();
-                    } catch (InterruptedException e) { }
-                    if (DBG) log("Event Loop thread finished");
-                    mThread = null;
-                }
-            };
-        if (DBG) log("Starting Event Loop thread");
-        mInterrupted = false;
-        mThread.start();
-    }
-    private native boolean setUpEventLoopNative();
-    private native void tearDownEventLoopNative();
-
-    public synchronized void stop() {
-        if (mThread != null) {
-            mInterrupted = true;
-            try {
-                mThread.join();
-                mThread = null;
-            } catch (InterruptedException e) {
-                Log.i(TAG, "Interrupted waiting for Event Loop thread to join");
-            }
+        if (!isEventLoopRunningNative()) {
+            if (DBG) log("Starting Event Loop thread");
+            startEventLoopNative();
         }
     }
 
-    public synchronized boolean isEventLoopRunning() {
-        return mThread != null && mStarted;
+    public void stop() {
+        if (isEventLoopRunningNative()) {
+            if (DBG) log("Stopping Event Loop thread");
+            stopEventLoopNative();
+        }
+    }
+
+    public boolean isEventLoopRunning() {
+        return isEventLoopRunningNative();
     }
 
     /*package*/ void onModeChanged(String bluezMode) {
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index fe15553..eaace6b 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -22,8 +22,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Handler;
-import android.util.Config;
 
 /**
  * This is a simplified version of the Search Manager service.  It no longer handles
@@ -36,7 +36,6 @@
         // general debugging support
     private static final String TAG = "SearchManagerService";
     private static final boolean DEBUG = false;
-    private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
     
         // configuration choices
     private static final boolean IMMEDIATE_SEARCHABLES_UPDATE = true;
@@ -45,9 +44,10 @@
     private final Context mContext;
     private final Handler mHandler;
     private boolean mSearchablesDirty;
+    private Searchables mSearchables;
     
     /**
-     * Initialize the Search Manager service in the provided system context.
+     * Initializes the Search Manager service in the provided system context.
      * Only one instance of this object should be created!
      *
      * @param context to use for accessing DB, window manager, etc.
@@ -55,6 +55,8 @@
     public SearchManagerService(Context context)  {     
         mContext = context;
         mHandler = new Handler();
+        mSearchablesDirty = true;
+        mSearchables = new Searchables(context);
         
         // Setup the infrastructure for updating and maintaining the list
         // of searchable activities.
@@ -64,7 +66,6 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
-        mSearchablesDirty = true;
         
         // After startup settles down, preload the searchables list,
         // which will reduce the delay when the search UI is invoked.
@@ -109,34 +110,41 @@
     };
 
     /**
-     * Update the list of searchables, either at startup or in response to
+     * Updates the list of searchables, either at startup or in response to
      * a package add/remove broadcast message.
      */
     private void updateSearchables() {
-        SearchableInfo.buildSearchableList(mContext);
+        mSearchables.buildSearchableList();
         mSearchablesDirty = false;
         
-        // TODO This is a hack.  This shouldn't be hardcoded here, it's probably
-        // a policy.
-//      ComponentName defaultSearch = new ComponentName( 
-//              "com.android.contacts", 
-//              "com.android.contacts.ContactsListActivity" );
-        ComponentName defaultSearch = new ComponentName( 
-                "com.android.googlesearch", 
-                "com.android.googlesearch.GoogleSearch" );
-        SearchableInfo.setDefaultSearchable(mContext, defaultSearch);
+        // TODO SearchableInfo should be the source of truth about whether a searchable exists.
+        // As it stands, if the package exists but is misconfigured in some way, then this
+        // would fail, and needs to be fixed.
+        ComponentName defaultSearch = new ComponentName(
+                "com.android.globalsearch", 
+                "com.android.globalsearch.GlobalSearch");
+        
+        try {
+            mContext.getPackageManager().getActivityInfo(defaultSearch, 0);
+        } catch (NameNotFoundException e) {
+            defaultSearch = new ComponentName(
+                    "com.android.googlesearch",
+                    "com.android.googlesearch.GoogleSearch");
+        }
+        
+        mSearchables.setDefaultSearchable(defaultSearch);
     }
 
     /**
-     * Return the searchableinfo for a given activity
+     * Returns the SearchableInfo for a given activity
      *
      * @param launchActivity The activity from which we're launching this search.
-     * @return Returns a SearchableInfo record describing the parameters of the search,
-     * or null if no searchable metadata was available.
      * @param globalSearch If false, this will only launch the search that has been specifically
      * defined by the application (which is usually defined as a local search).  If no default 
      * search is defined in the current application or activity, no search will be launched.
      * If true, this will always launch a platform-global (e.g. web-based) search instead.
+     * @return Returns a SearchableInfo record describing the parameters of the search,
+     * or null if no searchable metadata was available.
      */
     public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) {
         // final check.  however we should try to avoid this, because
@@ -146,11 +154,12 @@
         }
         SearchableInfo si = null;
         if (globalSearch) {
-            si = SearchableInfo.getDefaultSearchable();
+            si = mSearchables.getDefaultSearchable();
         } else {
-            si = SearchableInfo.getSearchableInfo(mContext, launchActivity);
+            si = mSearchables.getSearchableInfo(launchActivity);
         }
 
         return si;
     }
+
 }
diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java
index 0c04839..22abd1b 100644
--- a/core/java/android/server/search/SearchableInfo.java
+++ b/core/java/android/server/search/SearchableInfo.java
@@ -21,14 +21,11 @@
 
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.InputType;
@@ -38,9 +35,6 @@
 import android.view.inputmethod.EditorInfo;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
 
 public final class SearchableInfo implements Parcelable {
 
@@ -50,19 +44,12 @@
     // set this flag to 1 to prevent any apps from providing suggestions
     final static int DBG_INHIBIT_SUGGESTIONS = 0;
 
-    // static strings used for XML lookups, etc.
+    // static strings used for XML lookups.
     // TODO how should these be documented for the developer, in a more structured way than 
     // the current long wordy javadoc in SearchManager.java ?
-    private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable";
     private static final String MD_LABEL_SEARCHABLE = "android.app.searchable";
-    private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*";
     private static final String MD_XML_ELEMENT_SEARCHABLE = "searchable";
     private static final String MD_XML_ELEMENT_SEARCHABLE_ACTION_KEY = "actionkey";
-
-    // class maintenance and general shared data
-    private static HashMap<ComponentName, SearchableInfo> sSearchablesMap = null;
-    private static ArrayList<SearchableInfo> sSearchablesList = null;
-    private static SearchableInfo sDefaultSearchable = null;
     
     // true member variables - what we know about the searchability
     // TO-DO replace public with getters
@@ -86,7 +73,6 @@
     private String mSuggestIntentData = null;
     private ActionKeyInfo mActionKeyList = null;
     private String mSuggestProviderPackage = null;
-    private Context mCacheActivityContext = null;   // use during setup only - don't hold memory!
     
     // Flag values for Searchable_voiceSearchMode
     private static int VOICE_SEARCH_SHOW_BUTTON = 1;
@@ -97,37 +83,7 @@
     private int mVoicePromptTextId;         // voicePromptText
     private int mVoiceLanguageId;           // voiceLanguage
     private int mVoiceMaxResults;           // voiceMaxResults
-    
-    /**
-     * Set the default searchable activity (when none is specified).
-     */
-    public static void setDefaultSearchable(Context context, 
-                                            ComponentName activity) {
-        synchronized (SearchableInfo.class) {
-            SearchableInfo si = null;
-            if (activity != null) {
-                si = getSearchableInfo(context, activity);
-                if (si != null) {
-                    // move to front of list
-                    sSearchablesList.remove(si);
-                    sSearchablesList.add(0, si);
-                }
-            }
-            sDefaultSearchable = si;
-        }
-    }
-    
-    /**
-     * Provides the system-default search activity, which you can use
-     * whenever getSearchableInfo() returns null;
-     * 
-     * @return Returns the system-default search activity, null if never defined
-     */
-    public static SearchableInfo getDefaultSearchable() {
-        synchronized (SearchableInfo.class) {
-            return sDefaultSearchable;
-        }
-    }
+
     
     /**
      * Retrieve the authority for obtaining search suggestions.
@@ -193,9 +149,16 @@
      * @return Returns a context related to the searchable activity
      */
     public Context getActivityContext(Context context) {
+        return createActivityContext(context, mSearchActivity);
+    }
+    
+    /**
+     * Creates a context for another activity.
+     */
+    private static Context createActivityContext(Context context, ComponentName activity) {
         Context theirContext = null;
         try {
-            theirContext = context.createPackageContext(mSearchActivity.getPackageName(), 0);
+            theirContext = context.createPackageContext(activity.getPackageName(), 0);
         } catch (PackageManager.NameNotFoundException e) {
             // unexpected, but we deal with this by null-checking theirContext
         } catch (java.lang.SecurityException e) {
@@ -234,242 +197,68 @@
     }
     
     /**
-     * Factory.  Look up, or construct, based on the activity.
-     * 
-     * The activities fall into three cases, based on meta-data found in 
-     * the manifest entry:
-     * <ol>
-     * <li>The activity itself implements search.  This is indicated by the
-     * presence of a "android.app.searchable" meta-data attribute.
-     * The value is a reference to an XML file containing search information.</li>
-     * <li>A related activity implements search.  This is indicated by the
-     * presence of a "android.app.default_searchable" meta-data attribute.
-     * The value is a string naming the activity implementing search.  In this
-     * case the factory will "redirect" and return the searchable data.</li>
-     * <li>No searchability data is provided.  We return null here and other
-     * code will insert the "default" (e.g. contacts) search.
-     * 
-     * TODO: cache the result in the map, and check the map first.
-     * TODO: it might make sense to implement the searchable reference as
-     * an application meta-data entry.  This way we don't have to pepper each
-     * and every activity.
-     * TODO: can we skip the constructor step if it's a non-searchable?
-     * TODO: does it make sense to plug the default into a slot here for 
-     * automatic return?  Probably not, but it's one way to do it.
-     *
-     * @param activity The name of the current activity, or null if the 
-     * activity does not define any explicit searchable metadata.
-     */
-    public static SearchableInfo getSearchableInfo(Context context, 
-                                                   ComponentName activity) {
-        // Step 1.  Is the result already hashed?  (case 1)
-        SearchableInfo result;
-        synchronized (SearchableInfo.class) {
-            result = sSearchablesMap.get(activity);
-            if (result != null) return result;
-        }
-        
-        // Step 2.  See if the current activity references a searchable.
-        // Note:  Conceptually, this could be a while(true) loop, but there's
-        // no point in implementing reference chaining here and risking a loop.  
-        // References must point directly to searchable activities.
-       
-        ActivityInfo ai = null;
-        XmlPullParser xml = null;
-        try {
-            ai = context.getPackageManager().
-                       getActivityInfo(activity, PackageManager.GET_META_DATA );
-            String refActivityName = null;
-            
-            // First look for activity-specific reference
-            Bundle md = ai.metaData;
-            if (md != null) {
-                refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
-            }
-            // If not found, try for app-wide reference
-            if (refActivityName == null) {
-                md = ai.applicationInfo.metaData;
-                if (md != null) {
-                    refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
-                }
-            }
-            
-            // Irrespective of source, if a reference was found, follow it.
-            if (refActivityName != null)
-            {
-                // An app or activity can declare that we should simply launch 
-                // "system default search" if search is invoked.
-                if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
-                    return getDefaultSearchable();
-                }
-                String pkg = activity.getPackageName();
-                ComponentName referredActivity;
-                if (refActivityName.charAt(0) == '.') {
-                    referredActivity = new ComponentName(pkg, pkg + refActivityName);
-                } else {
-                    referredActivity = new ComponentName(pkg, refActivityName);
-                }
-
-                // Now try the referred activity, and if found, cache
-                // it against the original name so we can skip the check
-                synchronized (SearchableInfo.class) {
-                    result = sSearchablesMap.get(referredActivity);
-                    if (result != null) {
-                        sSearchablesMap.put(activity, result);
-                        return result;
-                    }
-                }
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // case 3: no metadata
-        }
- 
-        // Step 3.  None found. Return null.
-        return null;
-        
-    }
-    
-    /**
-     * Super-factory.  Builds an entire list (suitable for display) of 
-     * activities that are searchable, by iterating the entire set of 
-     * ACTION_SEARCH intents.  
-     * 
-     * Also clears the hash of all activities -> searches which will
-     * refill as the user clicks "search".
-     * 
-     * This should only be done at startup and again if we know that the
-     * list has changed.
-     * 
-     * TODO: every activity that provides a ACTION_SEARCH intent should
-     * also provide searchability meta-data.  There are a bunch of checks here
-     * that, if data is not found, silently skip to the next activity.  This
-     * won't help a developer trying to figure out why their activity isn't
-     * showing up in the list, but an exception here is too rough.  I would
-     * like to find a better notification mechanism.
-     * 
-     * TODO: sort the list somehow?  UI choice.
-     * 
-     * @param context a context we can use during this work
-     */
-    public static void buildSearchableList(Context context) {
-        
-        // create empty hash & list
-        HashMap<ComponentName, SearchableInfo> newSearchablesMap 
-                                = new HashMap<ComponentName, SearchableInfo>();
-        ArrayList<SearchableInfo> newSearchablesList
-                                = new ArrayList<SearchableInfo>();
-
-        // use intent resolver to generate list of ACTION_SEARCH receivers
-        final PackageManager pm = context.getPackageManager();
-        List<ResolveInfo> infoList;
-        final Intent intent = new Intent(Intent.ACTION_SEARCH);
-        infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
-        
-        // analyze each one, generate a Searchables record, and record
-        if (infoList != null) {
-            int count = infoList.size();
-            for (int ii = 0; ii < count; ii++) {
-                // for each component, try to find metadata
-                ResolveInfo info = infoList.get(ii);
-                ActivityInfo ai = info.activityInfo;
-                XmlResourceParser xml = ai.loadXmlMetaData(context.getPackageManager(), 
-                                                       MD_LABEL_SEARCHABLE);
-                if (xml == null) {
-                    continue;
-                }
-                ComponentName cName = new ComponentName(
-                        info.activityInfo.packageName, 
-                        info.activityInfo.name);
-                
-                SearchableInfo searchable = getActivityMetaData(context, xml, cName);
-                xml.close();
-                
-                if (searchable != null) {
-                    // no need to keep the context any longer.  setup time is over.
-                    searchable.mCacheActivityContext  = null;
-                    
-                    newSearchablesList.add(searchable);
-                    newSearchablesMap.put(cName, searchable);
-                }
-            }
-        }
-        
-        // record the final values as a coherent pair
-        synchronized (SearchableInfo.class) {
-            sSearchablesList = newSearchablesList;
-            sSearchablesMap = newSearchablesMap;
-        }
-    }
-    
-    /**
      * Constructor
      * 
      * Given a ComponentName, get the searchability info
      * and build a local copy of it.  Use the factory, not this.
      * 
-     * @param context runtime context
+     * @param activityContext runtime context for the activity that the searchable info is about.
      * @param attr The attribute set we found in the XML file, contains the values that are used to
      * construct the object.
      * @param cName The component name of the searchable activity
      */
-    private SearchableInfo(Context context, AttributeSet attr, final ComponentName cName) {
+    private SearchableInfo(Context activityContext, AttributeSet attr, final ComponentName cName) {
         // initialize as an "unsearchable" object
         mSearchable = false;
         mSearchActivity = cName;
         
-        // to access another activity's resources, I need its context.
-        // BE SURE to release the cache sometime after construction - it's a large object to hold
-        mCacheActivityContext = getActivityContext(context);
-        if (mCacheActivityContext != null) {
-            TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr,
-                    com.android.internal.R.styleable.Searchable);
-            mSearchMode = a.getInt(com.android.internal.R.styleable.Searchable_searchMode, 0);
-            mLabelId = a.getResourceId(com.android.internal.R.styleable.Searchable_label, 0);
-            mHintId = a.getResourceId(com.android.internal.R.styleable.Searchable_hint, 0);
-            mIconId = a.getResourceId(com.android.internal.R.styleable.Searchable_icon, 0);
-            mSearchButtonText = a.getResourceId(
-                    com.android.internal.R.styleable.Searchable_searchButtonText, 0);
-            mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType, 
-                    InputType.TYPE_CLASS_TEXT |
-                    InputType.TYPE_TEXT_VARIATION_NORMAL);
-            mSearchImeOptions = a.getInt(com.android.internal.R.styleable.Searchable_imeOptions, 
-                    EditorInfo.IME_ACTION_SEARCH);
+        TypedArray a = activityContext.obtainStyledAttributes(attr,
+                com.android.internal.R.styleable.Searchable);
+        mSearchMode = a.getInt(com.android.internal.R.styleable.Searchable_searchMode, 0);
+        mLabelId = a.getResourceId(com.android.internal.R.styleable.Searchable_label, 0);
+        mHintId = a.getResourceId(com.android.internal.R.styleable.Searchable_hint, 0);
+        mIconId = a.getResourceId(com.android.internal.R.styleable.Searchable_icon, 0);
+        mSearchButtonText = a.getResourceId(
+                com.android.internal.R.styleable.Searchable_searchButtonText, 0);
+        mSearchInputType = a.getInt(com.android.internal.R.styleable.Searchable_inputType, 
+                InputType.TYPE_CLASS_TEXT |
+                InputType.TYPE_TEXT_VARIATION_NORMAL);
+        mSearchImeOptions = a.getInt(com.android.internal.R.styleable.Searchable_imeOptions, 
+                EditorInfo.IME_ACTION_SEARCH);
 
-            setSearchModeFlags();
-            if (DBG_INHIBIT_SUGGESTIONS == 0) {
-                mSuggestAuthority = a.getString(
-                        com.android.internal.R.styleable.Searchable_searchSuggestAuthority);
-                mSuggestPath = a.getString(
-                        com.android.internal.R.styleable.Searchable_searchSuggestPath);
-                mSuggestSelection = a.getString(
-                        com.android.internal.R.styleable.Searchable_searchSuggestSelection);
-                mSuggestIntentAction = a.getString(
-                        com.android.internal.R.styleable.Searchable_searchSuggestIntentAction);
-                mSuggestIntentData = a.getString(
-                        com.android.internal.R.styleable.Searchable_searchSuggestIntentData);
-            }
-            mVoiceSearchMode = 
-                a.getInt(com.android.internal.R.styleable.Searchable_voiceSearchMode, 0);
-            // TODO this didn't work - came back zero from YouTube
-            mVoiceLanguageModeId = 
-                a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguageModel, 0);
-            mVoicePromptTextId = 
-                a.getResourceId(com.android.internal.R.styleable.Searchable_voicePromptText, 0);
-            mVoiceLanguageId = 
-                a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguage, 0);
-            mVoiceMaxResults = 
-                a.getInt(com.android.internal.R.styleable.Searchable_voiceMaxResults, 0);
+        setSearchModeFlags();
+        if (DBG_INHIBIT_SUGGESTIONS == 0) {
+            mSuggestAuthority = a.getString(
+                    com.android.internal.R.styleable.Searchable_searchSuggestAuthority);
+            mSuggestPath = a.getString(
+                    com.android.internal.R.styleable.Searchable_searchSuggestPath);
+            mSuggestSelection = a.getString(
+                    com.android.internal.R.styleable.Searchable_searchSuggestSelection);
+            mSuggestIntentAction = a.getString(
+                    com.android.internal.R.styleable.Searchable_searchSuggestIntentAction);
+            mSuggestIntentData = a.getString(
+                    com.android.internal.R.styleable.Searchable_searchSuggestIntentData);
+        }
+        mVoiceSearchMode = 
+            a.getInt(com.android.internal.R.styleable.Searchable_voiceSearchMode, 0);
+        // TODO this didn't work - came back zero from YouTube
+        mVoiceLanguageModeId = 
+            a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguageModel, 0);
+        mVoicePromptTextId = 
+            a.getResourceId(com.android.internal.R.styleable.Searchable_voicePromptText, 0);
+        mVoiceLanguageId = 
+            a.getResourceId(com.android.internal.R.styleable.Searchable_voiceLanguage, 0);
+        mVoiceMaxResults = 
+            a.getInt(com.android.internal.R.styleable.Searchable_voiceMaxResults, 0);
 
-            a.recycle();
+        a.recycle();
 
-            // get package info for suggestions provider (if any)
-            if (mSuggestAuthority != null) {
-                ProviderInfo pi =
-                    context.getPackageManager().resolveContentProvider(mSuggestAuthority,
-                            0);
-                if (pi != null) {
-                    mSuggestProviderPackage = pi.packageName;
-                }
+        // get package info for suggestions provider (if any)
+        if (mSuggestAuthority != null) {
+            PackageManager pm = activityContext.getPackageManager();
+            ProviderInfo pi = pm.resolveContentProvider(mSuggestAuthority, 0);
+            if (pi != null) {
+                mSuggestProviderPackage = pi.packageName;
             }
         }
 
@@ -496,7 +285,7 @@
     /**
      * Private class used to hold the "action key" configuration
      */
-    public class ActionKeyInfo implements Parcelable {
+    public static class ActionKeyInfo implements Parcelable {
         
         public int mKeyCode = 0;
         public String mQueryActionMsg;
@@ -506,14 +295,15 @@
         
         /**
          * Create one object using attributeset as input data.
-         * @param context runtime context
+         * @param activityContext runtime context of the activity that the action key information
+         *        is about.
          * @param attr The attribute set we found in the XML file, contains the values that are used to
          * construct the object.
          * @param next We'll build these up using a simple linked list (since there are usually
          * just zero or one).
          */
-        public ActionKeyInfo(Context context, AttributeSet attr, ActionKeyInfo next) {
-            TypedArray a = mCacheActivityContext.obtainStyledAttributes(attr,
+        public ActionKeyInfo(Context activityContext, AttributeSet attr, ActionKeyInfo next) {
+            TypedArray a = activityContext.obtainStyledAttributes(attr,
                     com.android.internal.R.styleable.SearchableActionKey);
 
             mKeyCode = a.getInt(
@@ -584,6 +374,20 @@
         return null;
     }
     
+    public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo) {
+        // for each component, try to find metadata
+        XmlResourceParser xml = 
+                activityInfo.loadXmlMetaData(context.getPackageManager(), MD_LABEL_SEARCHABLE);
+        if (xml == null) {
+            return null;
+        }
+        ComponentName cName = new ComponentName(activityInfo.packageName, activityInfo.name);
+        
+        SearchableInfo searchable = getActivityMetaData(context, xml, cName);
+        xml.close();
+        return searchable;
+    }
+    
     /**
      * Get the metadata for a given activity
      * 
@@ -598,6 +402,7 @@
     private static SearchableInfo getActivityMetaData(Context context, XmlPullParser xml,
             final ComponentName cName)  {
         SearchableInfo result = null;
+        Context activityContext = createActivityContext(context, cName);
         
         // in order to use the attributes mechanism, we have to walk the parser
         // forward through the file until it's reading the tag of interest.
@@ -608,7 +413,7 @@
                     if (xml.getName().equals(MD_XML_ELEMENT_SEARCHABLE)) {
                         AttributeSet attr = Xml.asAttributeSet(xml);
                         if (attr != null) {
-                            result = new SearchableInfo(context, attr, cName);
+                            result = new SearchableInfo(activityContext, attr, cName);
                             // if the constructor returned a bad object, exit now.
                             if (! result.mSearchable) {
                                 return null;
@@ -621,7 +426,7 @@
                         }
                         AttributeSet attr = Xml.asAttributeSet(xml);
                         if (attr != null) {
-                            ActionKeyInfo keyInfo = result.new ActionKeyInfo(context, attr, 
+                            ActionKeyInfo keyInfo = new ActionKeyInfo(activityContext, attr, 
                                     result.mActionKeyList);
                             // only add to list if it is was useable
                             if (keyInfo.mKeyCode != 0) {
@@ -637,6 +442,7 @@
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
+        
         return result;
     }
     
@@ -757,16 +563,6 @@
     }
     
     /**
-     * Return the list of searchable activities, for use in the drop-down.
-     */
-    public static ArrayList<SearchableInfo> getSearchablesList() {
-        synchronized (SearchableInfo.class) {
-            ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(sSearchablesList);
-            return result;
-        }
-    }
-    
-    /**
      * Support for parcelable and aidl operations.
      */
     public static final Parcelable.Creator<SearchableInfo> CREATOR
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
new file mode 100644
index 0000000..ba75d21
--- /dev/null
+++ b/core/java/android/server/search/Searchables.java
@@ -0,0 +1,243 @@
+/*
+ * 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.server.search;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * This class maintains the information about all searchable activities. 
+ */
+public class Searchables {
+
+    // static strings used for XML lookups, etc.
+    // TODO how should these be documented for the developer, in a more structured way than 
+    // the current long wordy javadoc in SearchManager.java ?
+    private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable";
+    private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*";
+    
+    private Context mContext;
+    
+    private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
+    private ArrayList<SearchableInfo> mSearchablesList = null;
+    private SearchableInfo mDefaultSearchable = null;
+    
+    /**
+     * 
+     * @param context Context to use for looking up activities etc.
+     */
+    public Searchables (Context context) {
+        mContext = context;
+    }
+    
+    /**
+     * Look up, or construct, based on the activity.
+     * 
+     * The activities fall into three cases, based on meta-data found in 
+     * the manifest entry:
+     * <ol>
+     * <li>The activity itself implements search.  This is indicated by the
+     * presence of a "android.app.searchable" meta-data attribute.
+     * The value is a reference to an XML file containing search information.</li>
+     * <li>A related activity implements search.  This is indicated by the
+     * presence of a "android.app.default_searchable" meta-data attribute.
+     * The value is a string naming the activity implementing search.  In this
+     * case the factory will "redirect" and return the searchable data.</li>
+     * <li>No searchability data is provided.  We return null here and other
+     * code will insert the "default" (e.g. contacts) search.
+     * 
+     * TODO: cache the result in the map, and check the map first.
+     * TODO: it might make sense to implement the searchable reference as
+     * an application meta-data entry.  This way we don't have to pepper each
+     * and every activity.
+     * TODO: can we skip the constructor step if it's a non-searchable?
+     * TODO: does it make sense to plug the default into a slot here for 
+     * automatic return?  Probably not, but it's one way to do it.
+     *
+     * @param activity The name of the current activity, or null if the 
+     * activity does not define any explicit searchable metadata.
+     */
+    public SearchableInfo getSearchableInfo(ComponentName activity) {
+        // Step 1.  Is the result already hashed?  (case 1)
+        SearchableInfo result;
+        synchronized (this) {
+            result = mSearchablesMap.get(activity);
+            if (result != null) return result;
+        }
+        
+        // Step 2.  See if the current activity references a searchable.
+        // Note:  Conceptually, this could be a while(true) loop, but there's
+        // no point in implementing reference chaining here and risking a loop.  
+        // References must point directly to searchable activities.
+       
+        ActivityInfo ai = null;
+        try {
+            ai = mContext.getPackageManager().
+                       getActivityInfo(activity, PackageManager.GET_META_DATA );
+            String refActivityName = null;
+            
+            // First look for activity-specific reference
+            Bundle md = ai.metaData;
+            if (md != null) {
+                refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
+            }
+            // If not found, try for app-wide reference
+            if (refActivityName == null) {
+                md = ai.applicationInfo.metaData;
+                if (md != null) {
+                    refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
+                }
+            }
+            
+            // Irrespective of source, if a reference was found, follow it.
+            if (refActivityName != null)
+            {
+                // An app or activity can declare that we should simply launch 
+                // "system default search" if search is invoked.
+                if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
+                    return getDefaultSearchable();
+                }
+                String pkg = activity.getPackageName();
+                ComponentName referredActivity;
+                if (refActivityName.charAt(0) == '.') {
+                    referredActivity = new ComponentName(pkg, pkg + refActivityName);
+                } else {
+                    referredActivity = new ComponentName(pkg, refActivityName);
+                }
+
+                // Now try the referred activity, and if found, cache
+                // it against the original name so we can skip the check
+                synchronized (this) {
+                    result = mSearchablesMap.get(referredActivity);
+                    if (result != null) {
+                        mSearchablesMap.put(activity, result);
+                        return result;
+                    }
+                }
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // case 3: no metadata
+        }
+ 
+        // Step 3.  None found. Return null.
+        return null;
+        
+    }
+    
+    /**
+     * Set the default searchable activity (when none is specified).
+     */
+    public synchronized void setDefaultSearchable(ComponentName activity) {
+        SearchableInfo si = null;
+        if (activity != null) {
+            si = getSearchableInfo(activity);
+            if (si != null) {
+                // move to front of list
+                mSearchablesList.remove(si);
+                mSearchablesList.add(0, si);
+            }
+        }
+        mDefaultSearchable = si;
+    }
+    
+    /**
+     * Provides the system-default search activity, which you can use
+     * whenever getSearchableInfo() returns null;
+     * 
+     * @return Returns the system-default search activity, null if never defined
+     */
+    public synchronized SearchableInfo getDefaultSearchable() {
+        return mDefaultSearchable;
+    }
+    
+    public synchronized boolean isDefaultSearchable(SearchableInfo searchable) {
+        return searchable == mDefaultSearchable;
+    }
+   
+    /**
+     * Builds an entire list (suitable for display) of 
+     * activities that are searchable, by iterating the entire set of 
+     * ACTION_SEARCH intents.  
+     * 
+     * Also clears the hash of all activities -> searches which will
+     * refill as the user clicks "search".
+     * 
+     * This should only be done at startup and again if we know that the
+     * list has changed.
+     * 
+     * TODO: every activity that provides a ACTION_SEARCH intent should
+     * also provide searchability meta-data.  There are a bunch of checks here
+     * that, if data is not found, silently skip to the next activity.  This
+     * won't help a developer trying to figure out why their activity isn't
+     * showing up in the list, but an exception here is too rough.  I would
+     * like to find a better notification mechanism.
+     * 
+     * TODO: sort the list somehow?  UI choice.
+     */
+    public void buildSearchableList() {
+        
+        // create empty hash & list
+        HashMap<ComponentName, SearchableInfo> newSearchablesMap 
+                                = new HashMap<ComponentName, SearchableInfo>();
+        ArrayList<SearchableInfo> newSearchablesList
+                                = new ArrayList<SearchableInfo>();
+
+        // use intent resolver to generate list of ACTION_SEARCH receivers
+        final PackageManager pm = mContext.getPackageManager();
+        List<ResolveInfo> infoList;
+        final Intent intent = new Intent(Intent.ACTION_SEARCH);
+        infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+        
+        // analyze each one, generate a Searchables record, and record
+        if (infoList != null) {
+            int count = infoList.size();
+            for (int ii = 0; ii < count; ii++) {
+                // for each component, try to find metadata
+                ResolveInfo info = infoList.get(ii);
+                ActivityInfo ai = info.activityInfo;
+                SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai);
+                if (searchable != null) {
+                    newSearchablesList.add(searchable);
+                    newSearchablesMap.put(searchable.mSearchActivity, searchable);
+                }
+            }
+        }
+        
+        // record the final values as a coherent pair
+        synchronized (this) {
+            mSearchablesList = newSearchablesList;
+            mSearchablesMap = newSearchablesMap;
+        }
+    }
+    
+    /**
+     * Returns the list of searchable activities.
+     */
+    public synchronized ArrayList<SearchableInfo> getSearchablesList() {
+        ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList);
+        return result;
+    }
+}
diff --git a/core/java/android/speech/IRecognitionListener.aidl b/core/java/android/speech/IRecognitionListener.aidl
new file mode 100644
index 0000000..6ed32b5
--- /dev/null
+++ b/core/java/android/speech/IRecognitionListener.aidl
@@ -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.
+ */
+
+package android.speech;
+
+import android.os.Bundle;
+
+/**
+ * Listener for speech recognition events, used with RecognitionService.
+ *  This gives you both the final recognition results, as well as various
+ *  intermediate events that can be used to show visual feedback to the user.
+ *  {@hide}
+ */
+interface IRecognitionListener {
+    /** Called when the endpointer is ready for the user to start speaking. */
+    void onReadyForSpeech(in Bundle noiseParams);
+
+    /** The user has started to speak. */
+    void onBeginningOfSpeech();
+
+    /** The sound level in the audio stream has changed. */
+    void onRmsChanged(in float rmsdB);
+
+    /**
+     * More sound has been received. Buffer is a byte buffer containing
+     * a sequence of 16-bit shorts. 
+     */
+    void onBufferReceived(in byte[] buffer);
+
+    /** Called after the user stops speaking. */
+    void onEndOfSpeech();
+
+    /** A network or recognition error occurred. */
+    void onError(in String error);
+
+    /** 
+     * Called when recognition transcripts are ready.
+     * results: an ordered list of the most likely transcripts (N-best list).
+     * @hide
+     */
+    void onResults(in List<String> results);
+}
diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl
new file mode 100644
index 0000000..8f06976
--- /dev/null
+++ b/core/java/android/speech/IRecognitionService.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.speech;
+
+import android.os.Bundle;
+import android.speech.IRecognitionListener;
+
+// A Service interface to speech recognition. Call startListening when
+// you want to begin capturing audio; RecognitionService will automatically
+// determine when the user has finished speaking, stream the audio to the
+// recognition servers, and notify you when results are ready.
+/** {@hide} */
+interface IRecognitionService {
+    // Start listening for speech. Can only call this from one thread at once.
+    void startListening(in Bundle recognitionParams,
+        in IRecognitionListener listener);
+
+    void cancel();
+}
diff --git a/core/java/android/speech/RecognitionServiceUtil.java b/core/java/android/speech/RecognitionServiceUtil.java
new file mode 100644
index 0000000..650c0fd
--- /dev/null
+++ b/core/java/android/speech/RecognitionServiceUtil.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+package android.speech;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+
+import java.util.List;
+
+/**
+ * Utils for Google's network-based speech recognizer, which lets you perform
+ * speech-to-text translation through RecognitionService. IRecognitionService
+ * and IRecognitionListener are the core interfaces; you begin recognition
+ * through IRecognitionService and subscribe to callbacks about when the user
+ * stopped speaking, results come in, errors, etc. through IRecognitionListener.
+ * RecognitionServiceUtil includes default IRecognitionListener and
+ * ServiceConnection implementations to reduce the amount of boilerplate.
+ *
+ * The Service provides no user interface. See RecognitionActivity if you
+ * want the standard voice search UI.
+ *
+ * Below is a small skeleton of how to use the recognizer:
+ *
+ * ServiceConnection conn = new RecognitionServiceUtil.Connection();
+ * mContext.bindService(RecognitionServiceUtil.sDefaultIntent,
+ *     conn, Context.BIND_AUTO_CREATE);
+ * IRecognitionListener listener = new RecognitionServiceWrapper.NullListener() {
+ *         public void onResults(List<String> results) {
+ *             // Do something with recognition transcripts
+ *         }
+ *     }
+ *
+ * // Must wait for conn.mService to be populated, then call below
+ * conn.mService.startListening(null, listener);
+ *
+ * {@hide}
+ */
+public class RecognitionServiceUtil {
+    public static final Intent sDefaultIntent = new Intent(
+            RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+
+    public static final String NOISE_LEVEL = "NoiseLevel";
+    public static final String SIGNAL_NOISE_RATIO = "SignalNoiseRatio";
+
+    private RecognitionServiceUtil() {}
+
+    /**
+     * IRecognitionListener which does nothing in response to recognition
+     * callbacks. You can subclass from this and override only the methods
+     * whose events you want to respond to.
+     */
+    public static class NullListener extends IRecognitionListener.Stub {
+        public void onReadyForSpeech(Bundle bundle) {}
+        public void onBeginningOfSpeech() {}
+        public void onRmsChanged(float rmsdB) {}
+        public void onBufferReceived(byte[] buf) {}
+        public void onEndOfSpeech() {}
+        public void onError(String error) {}
+        public void onResults(List<String> results) {}
+    }
+
+    /**
+     * Basic ServiceConnection which just records mService variable.
+     */
+    public static class Connection implements ServiceConnection {
+        public IRecognitionService mService;
+
+        public synchronized void onServiceConnected(ComponentName name, IBinder service) {
+            mService = IRecognitionService.Stub.asInterface(service);
+        }
+
+        public void onServiceDisconnected(ComponentName name) {
+            mService = null;
+        }
+    }
+}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index a6ed922..29dc2ea52 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -24,7 +24,6 @@
 import android.graphics.RectF;
 import android.graphics.Path;
 import com.android.internal.util.ArrayUtils;
-import android.util.Config;
 
 import junit.framework.Assert;
 import android.text.style.*;
@@ -39,6 +38,8 @@
  * For text that will not change, use a {@link StaticLayout}.
  */
 public abstract class Layout {
+    private static final boolean DEBUG = false;
+
     /* package */ static final EmojiFactory EMOJI_FACTORY =
         EmojiFactory.newAvailableInstance();
     /* package */ static final int MIN_EMOJI, MAX_EMOJI;
@@ -330,7 +331,7 @@
             boolean hasTab = getLineContainsTab(i);
             if (directions == DIRS_ALL_LEFT_TO_RIGHT &&
                     !spannedText && !hasTab) {
-                if (Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(dir == DIR_LEFT_TO_RIGHT);
                     Assert.assertNotNull(c);
                 }
@@ -797,7 +798,7 @@
     }
     
     private int getLineVisibleEnd(int line, int start, int end) {
-        if (Config.DEBUG) {
+        if (DEBUG) {
             Assert.assertTrue(getLineStart(line) == start && getLineStart(line+1) == end);
         }
 
@@ -1340,7 +1341,7 @@
         char[] buf;
         if (!hasTabs) {
             if (directions == DIRS_ALL_LEFT_TO_RIGHT) {
-                if (Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(DIR_LEFT_TO_RIGHT == dir);
                 }
                 Styled.drawText(canvas, text, start, end, dir, false, x, top, y, bottom, paint, workPaint, false);
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 1c5d669..56f389c 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -43,8 +43,8 @@
      *
      * <p>This class is useful for debugging and logging purpose:</p>
      * <pre>
-     * if (Config.DEBUG) {
-     *   if (DebugUtils.isObjectSelected(childView) && Config.LOGV) {
+     * if (DEBUG) {
+     *   if (DebugUtils.isObjectSelected(childView) && LOGV_ENABLED) {
      *     Log.v(TAG, "Object " + childView + " logged!");
      *   }
      * }
diff --git a/core/java/android/util/FinitePool.java b/core/java/android/util/FinitePool.java
new file mode 100644
index 0000000..3ef8293
--- /dev/null
+++ b/core/java/android/util/FinitePool.java
@@ -0,0 +1,86 @@
+/*
+ * 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.util;
+
+/**
+ * @hide
+ */
+class FinitePool<T extends Poolable<T>> implements Pool<T> {
+    /**
+     * Factory used to create new pool objects
+     */
+    private final PoolableManager<T> mManager;
+    /**
+     * Maximum number of objects in the pool
+     */
+    private final int mLimit;
+    /**
+     * If true, mLimit is ignored
+     */
+    private final boolean mInfinite;
+
+    /**
+     * Next object to acquire
+     */
+    private T mRoot;
+    /**
+     * Number of objects in the pool
+     */
+    private int mPoolCount;
+
+    FinitePool(PoolableManager<T> manager) {
+        mManager = manager;
+        mLimit = 0;
+        mInfinite = true;
+    }
+
+    FinitePool(PoolableManager<T> manager, int limit) {
+        if (limit <= 0) throw new IllegalArgumentException("The pool limit must be > 0");
+
+        mManager = manager;
+        mLimit = limit;
+        mInfinite = false;
+    }
+
+    public T acquire() {
+        T element;
+
+        if (mRoot != null) {
+            element = mRoot;
+            mRoot = element.getNextPoolable();
+            mPoolCount--;
+        } else {
+            element = mManager.newInstance();
+        }
+
+        if (element != null) {
+            element.setNextPoolable(null);
+            mManager.onAcquired(element);            
+        }
+
+        return element;
+    }
+
+    public void release(T element) {
+        if (mInfinite || mPoolCount < mLimit) {
+            mPoolCount++;
+            element.setNextPoolable(mRoot);
+            mRoot = element;
+        }
+        mManager.onReleased(element);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/core/java/android/util/Pool.java
similarity index 67%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to core/java/android/util/Pool.java
index 72790d0..8cd4f3e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/core/java/android/util/Pool.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 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,20 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package android.util;
 
 /**
- * {@hide}
+ * @hide
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
-
-    }
-
-    SimFileTypeMismatch(String s)
-    {
-        super(s);
-    }
+public interface Pool<T extends Poolable<T>> {
+    public abstract T acquire();
+    public abstract void release(T element);
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/core/java/android/util/Poolable.java
similarity index 67%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to core/java/android/util/Poolable.java
index 72790d0..fd9bd9b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/core/java/android/util/Poolable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 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,20 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package android.util;
 
 /**
- * {@hide}
+ * @hide
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
-
-    }
-
-    SimFileTypeMismatch(String s)
-    {
-        super(s);
-    }
+public interface Poolable<T> {
+    void setNextPoolable(T element);
+    T getNextPoolable();
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/core/java/android/util/PoolableManager.java
similarity index 67%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to core/java/android/util/PoolableManager.java
index 72790d0..8773e63 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/core/java/android/util/PoolableManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 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,20 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package android.util;
 
 /**
- * {@hide}
+ * @hide
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+public interface PoolableManager<T extends Poolable<T>> {
+    T newInstance();
 
-    }
-
-    SimFileTypeMismatch(String s)
-    {
-        super(s);
-    }
+    void onAcquired(T element);
+    void onReleased(T element);
 }
diff --git a/core/java/android/util/Pools.java b/core/java/android/util/Pools.java
new file mode 100644
index 0000000..8edb3e6
--- /dev/null
+++ b/core/java/android/util/Pools.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util;
+
+/**
+ * @hide
+ */
+public class Pools {
+    private Pools() {
+    }
+
+    public static <T extends Poolable<T>> Pool<T> simplePool(PoolableManager<T> manager) {
+        return new FinitePool<T>(manager);
+    }
+    
+    public static <T extends Poolable<T>> Pool<T> finitePool(PoolableManager<T> manager, int limit) {
+        return new FinitePool<T>(manager, limit);
+    }
+
+    public static <T extends Poolable<T>> Pool<T> synchronizedPool(Pool<T> pool) {
+        return new SynchronizedPool<T>(pool);
+    }
+
+    public static <T extends Poolable<T>> Pool<T> synchronizedPool(Pool<T> pool, Object lock) {
+        return new SynchronizedPool<T>(pool, lock);
+    }
+}
diff --git a/core/java/android/util/SynchronizedPool.java b/core/java/android/util/SynchronizedPool.java
new file mode 100644
index 0000000..651e0c3
--- /dev/null
+++ b/core/java/android/util/SynchronizedPool.java
@@ -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.
+ */
+
+package android.util;
+
+/**
+ *
+ * @hide
+ */
+class SynchronizedPool<T extends Poolable<T>> implements Pool<T> {
+    private final Pool<T> mPool;
+    private final Object mLock;
+
+    public SynchronizedPool(Pool<T> pool) {
+        mPool = pool;
+        mLock = this;
+    }
+
+    public SynchronizedPool(Pool<T> pool, Object lock) {
+        mPool = pool;
+        mLock = lock;
+    }
+
+    public T acquire() {
+        synchronized (mLock) {
+            return mPool.acquire();
+        }
+    }
+
+    public void release(T element) {
+        synchronized (mLock) {
+            mPool.release(element);
+        }
+    }
+}
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 882a079..2402660 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -102,7 +102,7 @@
     private float mYPrecision;
     private int mDeviceId;
     private int mEdgeFlags;
-    
+
     private MotionEvent mNext;
     private RuntimeException mRecycledLocation;
     private boolean mRecycled;
@@ -210,7 +210,29 @@
 
         return ev;
     }
-    
+
+    /**
+     * Scales down the cood of this event by the given scale.
+     *
+     * @hide
+     */
+    public void scale(float scale) {
+        if (scale != 1.0f) {
+            mX *= scale;
+            mY *= scale;
+            mRawX *= scale;
+            mRawY *= scale;
+            mSize *= scale;
+            mXPrecision *= scale;
+            mYPrecision *= scale;
+            float[] history = mHistory;
+            int length = history.length;
+            for (int i = 0; i < length; i++) {
+                history[i] *= scale;
+            }
+        }
+    }
+
     /**
      * Create a new MotionEvent, copying from an existing one.
      */
@@ -682,4 +704,3 @@
     }
 
 }
-
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index e928998..61dca4c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -135,20 +135,28 @@
     int mFormat = -1;
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
+    private final float mAppScale;
+    private final float mAppScaleInverted;
 
     public SurfaceView(Context context) {
         super(context);
         setWillNotDraw(true);
+        mAppScale = context.getApplicationScale();
+        mAppScaleInverted = 1.0f / mAppScale;
     }
     
     public SurfaceView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(true);
+        mAppScale = context.getApplicationScale();
+        mAppScaleInverted = 1.0f / mAppScale;
     }
 
     public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         setWillNotDraw(true);
+        mAppScale = context.getApplicationScale();
+        mAppScaleInverted = 1.0f / mAppScale;
     }
     
     /**
@@ -297,8 +305,8 @@
 
                 mLayout.x = mLeft;
                 mLayout.y = mTop;
-                mLayout.width = getWidth();
-                mLayout.height = getHeight();
+                mLayout.width = (int) (getWidth() * mAppScale);
+                mLayout.height = (int) (getHeight() * mAppScale);
                 mLayout.format = mRequestedFormat;
                 mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                               | WindowManager.LayoutParams.FLAG_SCALED
@@ -325,9 +333,14 @@
                 mSurfaceLock.lock();
                 mDrawingStopped = !visible;
                 final int relayoutResult = mSession.relayout(
-                        mWindow, mLayout, mWidth, mHeight,
+                    mWindow, mLayout, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale),
                         visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
                         mVisibleInsets, mSurface);
+
+                mContentInsets.scale(mAppScaleInverted);
+                mVisibleInsets.scale(mAppScaleInverted);
+                mWinFrame.scale(mAppScaleInverted);
+
                 if (localLOGV) Log.i(TAG, "New surface: " + mSurface
                         + ", vis=" + visible + ", frame=" + mWinFrame);
                 mSurfaceFrame.left = 0;
@@ -395,15 +408,25 @@
     }
 
     private static class MyWindow extends IWindow.Stub {
-        private WeakReference<SurfaceView> mSurfaceView;
+        private final WeakReference<SurfaceView> mSurfaceView;
+        private final float mAppScale;
+        private final float mAppScaleInverted;
 
         public MyWindow(SurfaceView surfaceView) {
             mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
+            mAppScale = surfaceView.getContext().getApplicationScale();
+            mAppScaleInverted = 1.0f / mAppScale;
         }
 
         public void resized(int w, int h, Rect coveredInsets,
                 Rect visibleInsets, boolean reportDraw) {
             SurfaceView surfaceView = mSurfaceView.get();
+            float scale = mAppScaleInverted;
+            w *= scale;
+            h *= scale;
+            coveredInsets.scale(scale);
+            visibleInsets.scale(scale);
+
             if (surfaceView != null) {
                 if (localLOGV) Log.v(
                         "SurfaceView", surfaceView + " got resized: w=" +
@@ -566,6 +589,7 @@
             Canvas c = null;
             if (!mDrawingStopped && mWindow != null) {
                 Rect frame = dirty != null ? dirty : mSurfaceFrame;
+                frame.scale(mAppScale);
                 try {
                     c = mSurface.lockCanvas(frame);
                 } catch (Exception e) {
@@ -611,4 +635,3 @@
         }
     };
 }
-
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 3951b2c3..c708f54 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -18,6 +18,10 @@
 
 import android.util.Config;
 import android.util.Log;
+import android.util.Poolable;
+import android.util.Pool;
+import android.util.Pools;
+import android.util.PoolableManager;
 
 /**
  * Helper for tracking the velocity of touch events, for implementing
@@ -28,53 +32,72 @@
  * {@link #computeCurrentVelocity(int)} and then {@link #getXVelocity()}
  * and {@link #getXVelocity()}.
  */
-public final class VelocityTracker {
+public final class VelocityTracker implements Poolable<VelocityTracker> {
     static final String TAG = "VelocityTracker";
     static final boolean DEBUG = false;
     static final boolean localLOGV = DEBUG || Config.LOGV;
-    
+
     static final int NUM_PAST = 10;
     static final int LONGEST_PAST_TIME = 200;
-    
+
     static final VelocityTracker[] mPool = new VelocityTracker[1];
-    
+    private static final Pool<VelocityTracker> sPool = Pools.synchronizedPool(
+            Pools.finitePool(new PoolableManager<VelocityTracker>() {
+                public VelocityTracker newInstance() {
+                    return new VelocityTracker();
+                }
+
+                public void onAcquired(VelocityTracker element) {
+                    element.clear();
+                }
+
+                public void onReleased(VelocityTracker element) {
+                }
+            }, 2));
+
     final float mPastX[] = new float[NUM_PAST];
     final float mPastY[] = new float[NUM_PAST];
     final long mPastTime[] = new long[NUM_PAST];
-   
+
     float mYVelocity;
     float mXVelocity;
-    
+
+    private VelocityTracker mNext;
+
     /**
      * Retrieve a new VelocityTracker object to watch the velocity of a
      * motion.  Be sure to call {@link #recycle} when done.  You should
      * generally only maintain an active object while tracking a movement,
      * so that the VelocityTracker can be re-used elsewhere.
-     * 
+     *
      * @return Returns a new VelocityTracker.
      */
     static public VelocityTracker obtain() {
-        synchronized (mPool) {
-            VelocityTracker vt = mPool[0];
-            if (vt != null) {
-                vt.clear();
-                mPool[0] = null;
-                return vt;
-            }
-            return new VelocityTracker();
-        }
+        return sPool.acquire();
     }
-    
+
     /**
      * Return a VelocityTracker object back to be re-used by others.  You must
      * not touch the object after calling this function.
      */
     public void recycle() {
-        synchronized (mPool) {
-            mPool[0] = this;
-        }
+        sPool.release(this);
     }
-    
+
+    /**
+     * @hide
+     */
+    public void setNextPoolable(VelocityTracker element) {
+        mNext = element;
+    }
+
+    /**
+     * @hide
+     */
+    public VelocityTracker getNextPoolable() {
+        return mNext;
+    }
+
     private VelocityTracker() {
     }
     
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0a84aa0..ec1c733 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -45,6 +45,10 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.Poolable;
+import android.util.Pool;
+import android.util.Pools;
+import android.util.PoolableManager;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.animation.Animation;
 import android.view.inputmethod.InputConnection;
@@ -7887,26 +7891,24 @@
          * For performance purposes, this class also implements a pool of up to
          * POOL_LIMIT objects that get reused. This reduces memory allocations
          * whenever possible.
-         *
-         * The pool is implemented as a linked list of InvalidateInfo object with
-         * the root pointing to the next available InvalidateInfo. If the root
-         * is null (i.e. when all instances from the pool have been acquired),
-         * then a new InvalidateInfo is created and returned to the caller.
-         *
-         * An InvalidateInfo is sent back to the pool by calling its release()
-         * method. If the pool is full the object is simply discarded.
-         *
-         * This implementation follows the object pool pattern used in the
-         * MotionEvent class.
          */
-        static class InvalidateInfo {
+        static class InvalidateInfo implements Poolable<InvalidateInfo> {
             private static final int POOL_LIMIT = 10;
-            private static final Object sLock = new Object();
+            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
+                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
+                        public InvalidateInfo newInstance() {
+                            return new InvalidateInfo();
+                        }
 
-            private static int sAcquiredCount = 0;
-            private static InvalidateInfo sRoot;
+                        public void onAcquired(InvalidateInfo element) {
+                        }
 
-            private InvalidateInfo next;
+                        public void onReleased(InvalidateInfo element) {
+                        }
+                    }, POOL_LIMIT)
+            );
+
+            private InvalidateInfo mNext;
 
             View target;
 
@@ -7915,28 +7917,20 @@
             int right;
             int bottom;
 
+            public void setNextPoolable(InvalidateInfo element) {
+                mNext = element;
+            }
+
+            public InvalidateInfo getNextPoolable() {
+                return mNext;
+            }
+
             static InvalidateInfo acquire() {
-                synchronized (sLock) {
-                    if (sRoot == null) {
-                        return new InvalidateInfo();
-                    }
-
-                    InvalidateInfo info = sRoot;
-                    sRoot = info.next;
-                    sAcquiredCount--;
-
-                    return info;
-                }
+                return sPool.acquire();
             }
 
             void release() {
-                synchronized (sLock) {
-                    if (sAcquiredCount < POOL_LIMIT) {
-                        sAcquiredCount++;
-                        next = sRoot;
-                        sRoot = this;
-                    }
-                }
+                sPool.release(this);
             }
         }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 18ee9ae..0b03626 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -128,6 +128,9 @@
     int mHeight;
     Rect mDirty; // will be a graphics.Region soon
     boolean mIsAnimating;
+    // TODO: change these to scaler class.
+    float mAppScale;
+    float mAppScaleInverted; // = 1.0f / mAppScale
 
     final View.AttachInfo mAttachInfo;
 
@@ -384,10 +387,12 @@
             View panelParentView) {
         synchronized (this) {
             if (mView == null) {
+                mView = view;
+                mAppScale = mView.getContext().getApplicationScale();
+                mAppScaleInverted = 1.0f / mAppScale;
                 mWindowAttributes.copyFrom(attrs);
                 mSoftInputMode = attrs.softInputMode;
                 mWindowAttributesChanged = true;
-                mView = view;
                 mAttachInfo.mRootView = view;
                 if (panelParentView != null) {
                     mAttachInfo.mPanelParentWindowToken
@@ -400,7 +405,7 @@
                 // manager, to make sure we do the relayout before receiving
                 // any other events from the system.
                 requestLayout();
-                
+
                 try {
                     res = sWindowSession.add(mWindow, attrs,
                             getHostVisibility(), mAttachInfo.mContentInsets);
@@ -411,6 +416,7 @@
                     unscheduleTraversals();
                     throw new RuntimeException("Adding window failed", e);
                 }
+                mAttachInfo.mContentInsets.scale(mAppScaleInverted);
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
                 if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow);
@@ -472,6 +478,8 @@
         synchronized (this) {
             int oldSoftInputMode = mWindowAttributes.softInputMode;
             mWindowAttributes.copyFrom(attrs);
+            mWindowAttributes.scale(mAppScale);
+
             if (newView) {
                 mSoftInputMode = attrs.softInputMode;
                 requestLayout();
@@ -521,9 +529,14 @@
     public void invalidateChild(View child, Rect dirty) {
         checkThread();
         if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
-        if (mCurScrollY != 0) {
+        if (mCurScrollY != 0 || mAppScale != 1.0f) {
             mTempRect.set(dirty);
-            mTempRect.offset(0, -mCurScrollY);
+            if (mCurScrollY != 0) {
+               mTempRect.offset(0, -mCurScrollY);
+            }
+            if (mAppScale != 1.0f) {
+                mTempRect.scale(mAppScale);
+            }
             dirty = mTempRect;
         }
         mDirty.union(dirty);
@@ -613,8 +626,8 @@
             mLayoutRequested = true;
 
             Display d = new Display(0);
-            desiredWindowWidth = d.getWidth();
-            desiredWindowHeight = d.getHeight();
+            desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
+            desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
 
             // For the very first time, tell the view hierarchy that it
             // is attached to the window.  Note that at this point the surface
@@ -683,8 +696,8 @@
                     windowResizesToFitContent = true;
 
                     Display d = new Display(0);
-                    desiredWindowWidth = d.getWidth();
-                    desiredWindowHeight = d.getHeight();
+                    desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
+                    desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
                 }
             }
 
@@ -792,10 +805,12 @@
                         params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
                     }
                 }
-                relayoutResult = sWindowSession.relayout(
-                    mWindow, params, host.mMeasuredWidth, host.mMeasuredHeight,
-                    viewVisibility, insetsPending, frame,
-                    mPendingContentInsets, mPendingVisibleInsets, mSurface);
+                if (DEBUG_LAYOUT) {
+                    Log.i(TAG, "host=w:" + host.mMeasuredWidth + ", h:" +
+                            host.mMeasuredHeight + ", params=" + params);
+                }
+                relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
+
                 if (params != null) {
                     params.flags = fl;
                 }
@@ -862,7 +877,7 @@
             mHeight = frame.height();
 
             if (initialized) {
-                mGlCanvas.setViewport(mWidth, mHeight);
+                mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
             }
 
             boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -944,6 +959,11 @@
                         mTmpLocation[1] + host.mBottom - host.mTop);
 
                 host.gatherTransparentRegion(mTransparentRegion);
+
+                // TODO: scale the region, like:
+                // Region uses native methods. We probabl should have ScalableRegion class.
+
+                // Region does not have equals method ?
                 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
@@ -974,6 +994,9 @@
             givenContent.left = givenContent.top = givenContent.right
                     = givenContent.bottom = givenVisible.left = givenVisible.top
                     = givenVisible.right = givenVisible.bottom = 0;
+            insets.contentInsets.scale(mAppScale);
+            insets.visibleInsets.scale(mAppScale);
+
             attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
             if (insetsPending || !mLastGivenInsets.equals(insets)) {
                 mLastGivenInsets.set(insets);
@@ -1113,7 +1136,7 @@
         
         int yoff;
         final boolean scrolling = mScroller != null
-                && mScroller.computeScrollOffset(); 
+                && mScroller.computeScrollOffset();
         if (scrolling) {
             yoff = mScroller.getCurrY();
         } else {
@@ -1135,10 +1158,19 @@
                     mGL.glEnable(GL_SCISSOR_TEST);
 
                     mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
-                    canvas.translate(0, -yoff);
                     mView.mPrivateFlags |= View.DRAWN;
-                    mView.draw(canvas);
-                    canvas.translate(0, yoff);
+
+                    float scale = mAppScale;
+                    int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+                    try {
+                        canvas.translate(0, -yoff);
+                        if (scale != 1.0f) {
+                            canvas.scale(scale, scale);
+                        }
+                        mView.draw(canvas);
+                    } finally {
+                        canvas.restoreToCount(saveCount);
+                    }
 
                     mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
                     checkEglErrors();
@@ -1160,7 +1192,7 @@
         }
 
         if (fullRedrawNeeded)
-            dirty.union(0, 0, mWidth, mHeight);
+            dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
 
         if (DEBUG_ORIENTATION || DEBUG_DRAW) {
             Log.v("ViewRoot", "Draw " + mView + "/"
@@ -1212,10 +1244,24 @@
                 dirty.setEmpty();
                 mIsAnimating = false;
                 mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
-                canvas.translate(0, -yoff);
-                mView.mPrivateFlags |= View.DRAWN;                    
-                mView.draw(canvas);
-                canvas.translate(0, yoff);
+                mView.mPrivateFlags |= View.DRAWN;
+
+                float scale = mAppScale;
+                Context cxt = mView.getContext();
+                if (DEBUG_DRAW) {
+                    Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + ", appScale=" + mAppScale);
+                }
+                int saveCount =  canvas.save(Canvas.MATRIX_SAVE_FLAG);
+                try {
+                    canvas.translate(0, -yoff);
+                    if (scale != 1.0f) {
+                        // re-scale this
+                        canvas.scale(scale, scale);
+                    }
+                    mView.draw(canvas);
+                } finally {
+                    canvas.restoreToCount(saveCount);
+                }
 
                 if (SHOW_FPS) {
                     int now = (int)SystemClock.elapsedRealtime();
@@ -1508,6 +1554,9 @@
             } else {
                 didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
             }
+            if (event != null) {
+                event.scale(mAppScaleInverted);
+            }
 
             try {
                 boolean handled;
@@ -1628,7 +1677,8 @@
                         if (mGlWanted && !mUseGL) {
                             initializeGL();
                             if (mGlCanvas != null) {
-                                mGlCanvas.setViewport(mWidth, mHeight);
+                                mGlCanvas.setViewport((int) (mWidth * mAppScale),
+                                        (int) (mHeight * mAppScale));
                             }
                         }
                     }
@@ -1828,6 +1878,9 @@
         } else {
             didFinish = false;
         }
+        if (event != null) {
+            event.scale(mAppScaleInverted);
+        }
 
         if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
 
@@ -2254,6 +2307,20 @@
         return mAudioManager;
     }
 
+    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
+            boolean insetsPending) throws RemoteException {
+        int relayoutResult = sWindowSession.relayout(
+                mWindow, params,
+                (int) (mView.mMeasuredWidth * mAppScale),
+                (int) (mView.mMeasuredHeight * mAppScale),
+                viewVisibility, insetsPending, mWinFrame,
+                mPendingContentInsets, mPendingVisibleInsets, mSurface);
+        mPendingContentInsets.scale(mAppScaleInverted);
+        mPendingVisibleInsets.scale(mAppScaleInverted);
+        mWinFrame.scale(mAppScaleInverted);
+        return relayoutResult;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -2322,12 +2389,8 @@
                     // to the window manager to make sure it has the correct
                     // animation info.
                     try {
-                        if ((sWindowSession.relayout(
-                                    mWindow, mWindowAttributes,
-                                    mView.mMeasuredWidth, mView.mMeasuredHeight,
-                                    viewVisibility, false, mWinFrame, mPendingContentInsets,
-                                    mPendingVisibleInsets, mSurface)
-                                &WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
+                        if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
+                                & WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {
                             sWindowSession.finishDrawing(mWindow);
                         }
                     } catch (RemoteException e) {
@@ -2361,8 +2424,11 @@
                 + " visibleInsets=" + visibleInsets.toShortString()
                 + " reportDraw=" + reportDraw);
         Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
-        msg.arg1 = w;
-        msg.arg2 = h;
+
+        coveredInsets.scale(mAppScaleInverted);
+        visibleInsets.scale(mAppScaleInverted);
+        msg.arg1 = (int) (w * mAppScaleInverted);
+        msg.arg2 = (int) (h * mAppScaleInverted);
         msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
         sendMessage(msg);
     }
@@ -2493,7 +2559,7 @@
                     sWindowSession.finishKey(mWindow);
                  } catch (RemoteException e) {
                  }
-            } else if (mIsPointer) {
+           } else if (mIsPointer) {
                 boolean didFinish;
                 MotionEvent event = mMotionEvent;
                 if (event == null) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index b87cc42..f6a171d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -953,7 +953,20 @@
             sb.append('}');
             return sb.toString();
         }
-    
+
+        void scale(float scale) {
+            if (scale != 1.0f) {
+                x *= scale;
+                y *= scale;
+                if (width > 0) {
+                    width *= scale;
+                }
+                if (height > 0) {
+                    height *= scale;
+                }
+            }
+        }
+
         private CharSequence mTitle = "";
     }
 }
diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
index fdb6f9d..158c56e 100644
--- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
+++ b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
@@ -28,6 +28,7 @@
     public AccelerateDecelerateInterpolator() {
     }
     
+    @SuppressWarnings({"UnusedDeclaration"})
     public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
     }
     
diff --git a/core/java/android/view/animation/AccelerateInterpolator.java b/core/java/android/view/animation/AccelerateInterpolator.java
index b9e293f0..dcab743 100644
--- a/core/java/android/view/animation/AccelerateInterpolator.java
+++ b/core/java/android/view/animation/AccelerateInterpolator.java
@@ -26,7 +26,12 @@
  *
  */
 public class AccelerateInterpolator implements Interpolator {
+    private final float mFactor;
+    private final double mDoubleFactor;
+
     public AccelerateInterpolator() {
+        mFactor = 1.0f;
+        mDoubleFactor = 2.0;
     }
     
     /**
@@ -39,6 +44,7 @@
      */
     public AccelerateInterpolator(float factor) {
         mFactor = factor;
+        mDoubleFactor = 2 * mFactor;
     }
     
     public AccelerateInterpolator(Context context, AttributeSet attrs) {
@@ -46,17 +52,16 @@
             context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator);
         
         mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);
-        
+        mDoubleFactor = 2 * mFactor;
+
         a.recycle();
     }
     
     public float getInterpolation(float input) {
         if (mFactor == 1.0f) {
-            return (float)(input * input);
+            return input * input;
         } else {
-            return (float)Math.pow(input, 2 * mFactor);
+            return (float)Math.pow(input, mDoubleFactor);
         }
     }
-    
-    private float mFactor = 1.0f;
 }
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index ce3cdc5..3088382 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -63,15 +63,13 @@
             parser = context.getResources().getAnimation(id);
             return createAnimationFromXml(context, parser);
         } catch (XmlPullParserException ex) {
-            NotFoundException rnf = new NotFoundException(
-                    "Can't load animation resource ID #0x"
-                            + Integer.toHexString(id));
+            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
+                    Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } catch (IOException ex) {
-            NotFoundException rnf = new NotFoundException(
-                    "Can't load animation resource ID #0x"
-                            + Integer.toHexString(id));
+            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
+                    Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } finally {
@@ -81,16 +79,17 @@
 
     private static Animation createAnimationFromXml(Context c, XmlPullParser parser)
             throws XmlPullParserException, IOException {
+
         return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
     }
     
-    private static Animation createAnimationFromXml(Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs)
-    throws XmlPullParserException, IOException {
+    private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
+            AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
         
         Animation anim = null;
  
         // Make sure we are on a start tag.
-        int type = parser.getEventType();
+        int type;
         int depth = parser.getDepth();
 
         while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
@@ -126,23 +125,21 @@
 
     }
 
-    public static LayoutAnimationController loadLayoutAnimation(
-            Context context, int id) throws NotFoundException {
+    public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
+            throws NotFoundException {
         
         XmlResourceParser parser = null;
         try {
             parser = context.getResources().getAnimation(id);
             return createLayoutAnimationFromXml(context, parser);
         } catch (XmlPullParserException ex) {
-            NotFoundException rnf = new NotFoundException(
-                    "Can't load animation resource ID #0x" +
-                            Integer.toHexString(id));
+            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
+                    Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } catch (IOException ex) {
-            NotFoundException rnf = new NotFoundException(
-                    "Can't load animation resource ID #0x" +
-                            Integer .toHexString(id));
+            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
+                    Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } finally {
@@ -150,24 +147,21 @@
         }
     }
 
-    private static LayoutAnimationController createLayoutAnimationFromXml(
-            Context c, XmlPullParser parser)
-            throws XmlPullParserException, IOException {
-        return createLayoutAnimationFromXml(c, parser,
-                Xml.asAttributeSet(parser));
+    private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
+            XmlPullParser parser) throws XmlPullParserException, IOException {
+
+        return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
     }
 
-    private static LayoutAnimationController createLayoutAnimationFromXml(
-            Context c, XmlPullParser parser, AttributeSet attrs)
-            throws XmlPullParserException, IOException {
+    private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
+            XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
 
         LayoutAnimationController controller = null;
 
         int type;
         int depth = parser.getDepth();
 
-        while (((type = parser.next()) != XmlPullParser.END_TAG
-                || parser.getDepth() > depth)
+        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
                 && type != XmlPullParser.END_DOCUMENT) {
 
             if (type != XmlPullParser.START_TAG) {
@@ -181,8 +175,7 @@
             } else if ("gridLayoutAnimation".equals(name)) {
                 controller = new GridLayoutAnimationController(c, attrs);
             } else {
-                throw new RuntimeException("Unknown layout animation name: " +
-                        name);
+                throw new RuntimeException("Unknown layout animation name: " + name);
             }
         }
 
@@ -197,9 +190,7 @@
      * @param fromLeft is the object to be animated coming from the left
      * @return The new animation
      */
-    public static Animation makeInAnimation(Context c, boolean fromLeft)
-    {
-        
+    public static Animation makeInAnimation(Context c, boolean fromLeft) {
         Animation a;
         if (fromLeft) {
             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_left);
@@ -220,9 +211,7 @@
      * @param toRight is the object to be animated exiting to the right
      * @return The new animation
      */
-    public static Animation makeOutAnimation(Context c, boolean toRight)
-    {   
-        
+    public static Animation makeOutAnimation(Context c, boolean toRight) {
         Animation a;
         if (toRight) {
             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_right);
@@ -243,9 +232,7 @@
      * @param c Context for loading resources
      * @return The new animation
      */
-    public static Animation makeInChildBottomAnimation(Context c)
-    {   
-
+    public static Animation makeInChildBottomAnimation(Context c) {
         Animation a;
         a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_child_bottom);
         a.setInterpolator(new AccelerateInterpolator());
@@ -261,23 +248,19 @@
      * @return The animation object reference by the specified id
      * @throws NotFoundException
      */
-    public static Interpolator loadInterpolator(Context context, int id)
-            throws NotFoundException {
-
+    public static Interpolator loadInterpolator(Context context, int id) throws NotFoundException {
         XmlResourceParser parser = null;
         try {
             parser = context.getResources().getAnimation(id);
             return createInterpolatorFromXml(context, parser);
         } catch (XmlPullParserException ex) {
-            NotFoundException rnf = new NotFoundException(
-                    "Can't load animation resource ID #0x"
-                            + Integer.toHexString(id));
+            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
+                    Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } catch (IOException ex) {
-            NotFoundException rnf = new NotFoundException(
-                    "Can't load animation resource ID #0x"
-                            + Integer.toHexString(id));
+            NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
+                    Integer.toHexString(id));
             rnf.initCause(ex);
             throw rnf;
         } finally {
@@ -287,12 +270,12 @@
     }
     
     private static Interpolator createInterpolatorFromXml(Context c, XmlPullParser parser)
-    throws XmlPullParserException, IOException {
+            throws XmlPullParserException, IOException {
         
         Interpolator interpolator = null;
  
         // Make sure we are on a start tag.
-        int type = parser.getEventType();
+        int type;
         int depth = parser.getDepth();
 
         while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
@@ -317,6 +300,14 @@
                 interpolator = new AccelerateDecelerateInterpolator(c, attrs);
             }  else if (name.equals("cycleInterpolator")) {
                 interpolator = new CycleInterpolator(c, attrs);
+            } else if (name.equals("anticipateInterpolator")) {
+                interpolator = new AnticipateInterpolator(c, attrs);
+            } else if (name.equals("overshootInterpolator")) {
+                interpolator = new OvershootInterpolator(c, attrs);
+            } else if (name.equals("anticipateOvershootInterpolator")) {
+                interpolator = new AnticipateOvershootInterpolator(c, attrs);
+            } else if (name.equals("bounceInterpolator")) {
+                interpolator = new BounceInterpolator(c, attrs);
             } else {
                 throw new RuntimeException("Unknown interpolator name: " + parser.getName());
             }
diff --git a/core/java/android/view/animation/AnticipateInterpolator.java b/core/java/android/view/animation/AnticipateInterpolator.java
new file mode 100644
index 0000000..a6f110e
--- /dev/null
+++ b/core/java/android/view/animation/AnticipateInterpolator.java
@@ -0,0 +1,56 @@
+/*
+ * 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.view.animation;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+
+/**
+ * An interpolator where the change starts backward then flings forward.
+ */
+public class AnticipateInterpolator implements Interpolator {
+    private final float mTension;
+
+    public AnticipateInterpolator() {
+        mTension = 2.0f;
+    }
+
+    /**
+     * @param tension Amount of anticipation. When tension equals 0.0f, there is
+     *                no anticipation and the interpolator becomes a simple
+     *                acceleration interpolator.
+     */
+    public AnticipateInterpolator(float tension) {
+        mTension = tension;
+    }
+
+    public AnticipateInterpolator(Context context, AttributeSet attrs) {
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.AnticipateInterpolator);
+
+        mTension =
+                a.getFloat(com.android.internal.R.styleable.AnticipateInterpolator_tension, 2.0f);
+
+        a.recycle();
+    }
+
+    public float getInterpolation(float t) {
+        // a(t) = t * t * ((tension + 1) * t - tension)
+        return t * t * ((mTension + 1) * t - mTension);
+    }
+}
diff --git a/core/java/android/view/animation/AnticipateOvershootInterpolator.java b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
new file mode 100644
index 0000000..3dc9722
--- /dev/null
+++ b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
@@ -0,0 +1,83 @@
+/*
+ * 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.view.animation;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_extraTension;
+import static com.android.internal.R.styleable.AnticipateOvershootInterpolator_tension;
+import static com.android.internal.R.styleable.AnticipateOvershootInterpolator;
+
+/**
+ * An interpolator where the change starts backward then flings forward and overshoots
+ * the target value and finally goes back to the final value.
+ */
+public class AnticipateOvershootInterpolator implements Interpolator {
+    private final float mTension;
+
+    public AnticipateOvershootInterpolator() {
+        mTension = 2.0f * 1.5f;
+    }
+
+    /**
+     * @param tension Amount of anticipation/overshoot. When tension equals 0.0f,
+     *                there is no anticipation/overshoot and the interpolator becomes
+     *                a simple acceleration/deceleration interpolator.
+     */
+    public AnticipateOvershootInterpolator(float tension) {
+        mTension = tension * 1.5f;
+    }
+
+    /**
+     * @param tension Amount of anticipation/overshoot. When tension equals 0.0f,
+     *                there is no anticipation/overshoot and the interpolator becomes
+     *                a simple acceleration/deceleration interpolator.
+     * @param extraTension Amount by which to multiply the tension. For instance,
+     *                     to get the same overshoot as an OvershootInterpolator with
+     *                     a tension of 2.0f, you would use an extraTension of 1.5f.
+     */
+    public AnticipateOvershootInterpolator(float tension, float extraTension) {
+        mTension = tension * extraTension;
+    }
+
+    public AnticipateOvershootInterpolator(Context context, AttributeSet attrs) {
+        TypedArray a = context.obtainStyledAttributes(attrs, AnticipateOvershootInterpolator);
+
+        mTension = a.getFloat(AnticipateOvershootInterpolator_tension, 2.0f) *
+                a.getFloat(AnticipateOvershootInterpolator_extraTension, 1.5f);
+
+        a.recycle();
+    }
+
+    private static float a(float t, float s) {
+        return t * t * ((s + 1) * t - s);
+    }
+
+    private static float o(float t, float s) {
+        return t * t * ((s + 1) * t + s);
+    }
+
+    public float getInterpolation(float t) {
+        // a(t, s) = t * t * ((s + 1) * t - s)
+        // o(t, s) = t * t * ((s + 1) * t + s)
+        // f(t) = 0.5 * a(t * 2, tension * extraTension), when t < 0.5
+        // f(t) = 0.5 * (o(t * 2 - 2, tension * extraTension) + 2), when t <= 1.0
+        if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension);
+        else return 0.5f * (o(t * 2.0f - 2.0f, mTension) + 2.0f);
+    }
+}
diff --git a/core/java/android/view/animation/BounceInterpolator.java b/core/java/android/view/animation/BounceInterpolator.java
new file mode 100644
index 0000000..f79e730
--- /dev/null
+++ b/core/java/android/view/animation/BounceInterpolator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.view.animation;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+
+/**
+ * An interpolator where the change bounces at the end.
+ */
+public class BounceInterpolator implements Interpolator {
+    public BounceInterpolator() {
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    public BounceInterpolator(Context context, AttributeSet attrs) {
+    }
+
+    private static float bounce(float t) {
+        return t * t * 8.0f;
+    }
+
+    public float getInterpolation(float t) {
+        // _b(t) = t * t * 8
+        // bs(t) = _b(t) for t < 0.3535
+        // bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408
+        // bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644
+        // bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0
+        // b(t) = bs(t * 1.1226)
+        t *= 1.1226f;
+        if (t < 0.3535f) return bounce(t);
+        else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;
+        else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
+        else return bounce(t - 1.0435f) + 0.95f;
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/view/animation/OvershootInterpolator.java b/core/java/android/view/animation/OvershootInterpolator.java
new file mode 100644
index 0000000..494f8ab
--- /dev/null
+++ b/core/java/android/view/animation/OvershootInterpolator.java
@@ -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.view.animation;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+
+/**
+ * An interpolator where the change flings forward and overshoots the last value
+ * then comes back.
+ */
+public class OvershootInterpolator implements Interpolator {
+    private final float mTension;
+
+    public OvershootInterpolator() {
+        mTension = 2.0f;
+    }
+
+    /**
+     * @param tension Amount of overshoot. When tension equals 0.0f, there is
+     *                no overshoot and the interpolator becomes a simple
+     *                deceleration interpolator.
+     */
+    public OvershootInterpolator(float tension) {
+        mTension = tension;
+    }
+
+    public OvershootInterpolator(Context context, AttributeSet attrs) {
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.OvershootInterpolator);
+
+        mTension =
+                a.getFloat(com.android.internal.R.styleable.OvershootInterpolator_tension, 2.0f);
+
+        a.recycle();
+    }
+
+    public float getInterpolation(float t) {
+        // _o(t) = t * t * ((tension + 1) * t + tension)
+        // o(t) = _o(t - 1) + 1
+        t -= 1.0f;
+        return t * t * ((mTension + 1) * t + mTension) + 1.0f;
+    }
+}
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index f9e85bf..cf210c8 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -18,6 +18,8 @@
 
 import android.graphics.Matrix;
 
+import java.io.PrintWriter;
+
 /**
  * Defines the transformation to be applied at
  * one point in time of an Animation.
@@ -134,14 +136,38 @@
     
     @Override
     public String toString() {
-        return "Transformation{alpha=" + mAlpha + " matrix="
-                + mMatrix.toShortString() + "}";
+        StringBuilder sb = new StringBuilder(64);
+        sb.append("Transformation");
+        toShortString(sb);
+        return sb.toString();
     }
     
     /**
      * Return a string representation of the transformation in a compact form.
      */
     public String toShortString() {
-        return "{alpha=" + mAlpha + " matrix=" + mMatrix.toShortString() + "}";
+        StringBuilder sb = new StringBuilder(64);
+        toShortString(sb);
+        return sb.toString();
+    }
+    
+    /**
+     * @hide
+     */
+    public void toShortString(StringBuilder sb) {
+        sb.append("{alpha="); sb.append(mAlpha);
+        sb.append(" matrix="); mMatrix.toShortString(sb);
+        sb.append('}');
+    }
+    
+    /**
+     * Print short string, to optimize dumping.
+     * @hide
+     */
+    public void printShortString(PrintWriter pw) {
+        pw.print("{alpha="); pw.print(mAlpha);
+        pw.print(" matrix=");
+        mMatrix.printShortString(pw);
+        pw.print('}');
     }
 }
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 5401a6e..ba3f78c 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -24,7 +24,6 @@
 import android.net.http.SslCertificate;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 import android.util.TypedValue;
 
@@ -120,7 +119,7 @@
         mDatabase = WebViewDatabase.getInstance(context);
         mWebViewCore = w;
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "BrowserFrame constructor: this=" + this);
         }
     }
@@ -331,7 +330,7 @@
         switch (msg.what) {
             case FRAME_COMPLETED: {
                 if (mSettings.getSavePassword() && hasPasswordField()) {
-                    if (Config.DEBUG) {
+                    if (WebView.DEBUG) {
                         Assert.assertNotNull(mCallbackProxy.getBackForwardList()
                                 .getCurrentItem());
                     }
@@ -480,7 +479,7 @@
             }
             if (mSettings.getSavePassword() && hasPasswordField()) {
                 try {
-                    if (Config.DEBUG) {
+                    if (WebView.DEBUG) {
                         Assert.assertNotNull(mCallbackProxy.getBackForwardList()
                                 .getCurrentItem());
                     }
@@ -528,7 +527,7 @@
         // is this resource the main-frame top-level page?
         boolean isMainFramePage = mIsMainFrame;
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "startLoadingResource: url=" + url + ", method="
                     + method + ", postData=" + postData + ", isHighPriority="
                     + isHighPriority + ", isMainFramePage=" + isMainFramePage);
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 4528b73..7897435 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.net.http.Headers;
 import android.os.FileUtils;
-import android.util.Config;
 import android.util.Log;
 import java.io.File;
 import java.io.FileInputStream;
@@ -322,7 +321,7 @@
             }
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "getCacheFile for url " + url);
         }
 
@@ -416,7 +415,7 @@
 
         mDataBase.addCache(url, cacheRet);
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "saveCacheFile for url " + url);
         }
     }
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 0f9f29c..5f8acc8 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -30,7 +30,6 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.provider.Browser;
-import android.util.Config;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -822,7 +821,7 @@
             String password, Message resumeMsg) {
         // resumeMsg should be null at this point because we want to create it
         // within the CallbackProxy.
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             junit.framework.Assert.assertNull(resumeMsg);
         }
         resumeMsg = obtainMessage(NOTIFY);
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index d90a2fd..c0c6775 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -18,7 +18,6 @@
 
 import android.net.ParseException;
 import android.net.WebAddress;
-import android.util.Config;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -263,7 +262,7 @@
         if (!mAcceptCookie || uri == null) {
             return;
         }
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "setCookie: uri: " + uri + " value: " + value);
         }
 
@@ -428,12 +427,12 @@
             }
         }
         if (ret.length() > 0) {
-            if (Config.LOGV) {
+            if (WebView.LOGV_ENABLED) {
                 Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret);
             }
             return ret.toString();
         } else {
-            if (Config.LOGV) {
+            if (WebView.LOGV_ENABLED) {
                 Log.v(LOGTAG, "getCookie: uri: " + uri
                         + " But can't find cookie.");
             }
@@ -589,7 +588,7 @@
             Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator();
             while (listIter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
                 ArrayList<Cookie> list = listIter.next();
-                if (Config.DEBUG) {
+                if (WebView.DEBUG) {
                     Iterator<Cookie> iter = list.iterator();
                     while (iter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
                         Cookie cookie = iter.next();
@@ -609,7 +608,7 @@
 
         ArrayList<Cookie> retlist = new ArrayList<Cookie>();
         if (mapSize >= MAX_RAM_DOMAIN_COUNT || count >= MAX_RAM_COOKIES_COUNT) {
-            if (Config.DEBUG) {
+            if (WebView.DEBUG) {
                 Log.v(LOGTAG, count + " cookies used " + byteCount
                         + " bytes with " + mapSize + " domains");
             }
@@ -617,7 +616,7 @@
             int toGo = mapSize / 10 + 1;
             while (toGo-- > 0){
                 String domain = domains[toGo].toString();
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "delete domain: " + domain
                             + " from RAM cache");
                 }
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index f2511d8..8d66529 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -17,7 +17,6 @@
 package android.webkit;
 
 import android.content.Context;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CookieManager.Cookie;
 
@@ -162,7 +161,7 @@
     }
 
     protected void syncFromRamToFlash() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash STARTS");
         }
 
@@ -179,7 +178,7 @@
                 CookieManager.getInstance().deleteLRUDomain();
         syncFromRamToFlash(lruList);
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash DONE");
         }
     }
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 42d03f0..6f1b160 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -18,7 +18,6 @@
 
 import android.net.http.EventHandler;
 import android.net.http.RequestHandle;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
 
@@ -121,7 +120,7 @@
         } else if (handleLocalFile(url, mListener, mSettings)) {
             return true;
         }
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "FrameLoader.executeLoad: url protocol not supported:"
                     + mListener.url());
         }
@@ -181,7 +180,7 @@
             return true;
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "FrameLoader: http " + mMethod + " load for: "
                     + mListener.url());
         }
@@ -212,7 +211,7 @@
      * setup a load from the byte stream in a CacheResult.
      */
     private void startCacheLoad(CacheResult result) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "FrameLoader: loading from cache: "
                   + mListener.url());
         }
@@ -286,7 +285,7 @@
             // of it's state. If it is not in the cache, then go to the 
             // network.
             case WebSettings.LOAD_CACHE_ELSE_NETWORK: {
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "FrameLoader: checking cache: "
                             + mListener.url());
                 }
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index a0049ac..2a84683 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -18,7 +18,6 @@
 
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 
 final class JWebCoreJavaBridge extends Handler {
@@ -156,7 +155,7 @@
      * @param timemillis The relative time when the timer should fire
      */
     private void setSharedTimer(long timemillis) {
-        if (Config.LOGV) Log.v(LOGTAG, "setSharedTimer " + timemillis);
+        if (WebView.LOGV_ENABLED) Log.v(LOGTAG, "setSharedTimer " + timemillis);
 
         if (timemillis <= 0) {
             // we don't accumulate the sharedTimer unless it is a delayed
@@ -180,7 +179,7 @@
      * Stop the shared timer.
      */
     private void stopSharedTimer() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "stopSharedTimer removing all timers");
         }
         removeMessages(TIMER_MESSAGE);
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index c64200cd..d583eb1 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -29,7 +29,6 @@
 
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
 
@@ -134,7 +133,7 @@
 
     LoadListener(Context context, BrowserFrame frame, String url,
             int nativeLoader, boolean synchronous, boolean isMainPageLoader) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener constructor url=" + url);
         }
         mContext = context;
@@ -285,7 +284,7 @@
      * directly
      */
     public void headers(Headers headers) {
-        if (Config.LOGV) Log.v(LOGTAG, "LoadListener.headers");
+        if (WebView.LOGV_ENABLED) Log.v(LOGTAG, "LoadListener.headers");
         sendMessageInternal(obtainMessage(MSG_CONTENT_HEADERS, headers));
     }
 
@@ -432,7 +431,7 @@
      */
     public void status(int majorVersion, int minorVersion,
             int code, /* Status-Code value */ String reasonPhrase) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener: from: " + mUrl
                     + " major: " + majorVersion
                     + " minor: " + minorVersion
@@ -489,7 +488,7 @@
      * directly
      */
     public void error(int id, String description) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.error url:" +
                     url() + " id:" + id + " description:" + description);
         }
@@ -517,7 +516,7 @@
      * mDataBuilder is a thread-safe structure.
      */
     public void data(byte[] data, int length) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.data(): url: " + url());
         }
 
@@ -555,7 +554,7 @@
      * directly
      */
     public void endData() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.endData(): url: " + url());
         }
         sendMessageInternal(obtainMessage(MSG_CONTENT_FINISHED));
@@ -608,7 +607,7 @@
                 // before calling it.
                 if (mCacheLoader != null) {
                     mCacheLoader.load();
-                    if (Config.LOGV) {
+                    if (WebView.LOGV_ENABLED) {
                         Log.v(LOGTAG, "LoadListener cache load url=" + url());
                     }
                     return;
@@ -658,7 +657,7 @@
                     CacheManager.HEADER_KEY_IFNONEMATCH) &&
                     !headers.containsKey(
                             CacheManager.HEADER_KEY_IFMODIFIEDSINCE)) {
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "FrameLoader: HTTP URL in cache " +
                             "and usable: " + url());
                 }
@@ -677,7 +676,7 @@
      * directly
      */
     public void handleSslErrorRequest(SslError error) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG,
                     "LoadListener.handleSslErrorRequest(): url:" + url() +
                     " primary error: " + error.getPrimaryError() +
@@ -743,7 +742,7 @@
      * are null, cancel the request.
      */
     void handleAuthResponse(String username, String password) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.handleAuthResponse: url: " + mUrl
                     + " username: " + username
                     + " password: " + password);
@@ -840,7 +839,7 @@
     }
 
     void attachRequestHandle(RequestHandle requestHandle) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.attachRequestHandle(): " +
                     "requestHandle: " +  requestHandle);
         }
@@ -848,7 +847,7 @@
     }
 
     void detachRequestHandle() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.detachRequestHandle(): " +
                     "requestHandle: " + mRequestHandle);
         }
@@ -887,7 +886,7 @@
      */
     static boolean willLoadFromCache(String url) {
         boolean inCache = CacheManager.getCacheFile(url, null) != null;
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "willLoadFromCache: " + url + " in cache: " + 
                     inCache);
         }
@@ -1057,7 +1056,7 @@
      * EventHandler's method call.
      */
     public void cancel() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             if (mRequestHandle == null) {
                 Log.v(LOGTAG, "LoadListener.cancel(): no requestHandle");
             } else {
@@ -1189,7 +1188,7 @@
             tearDown();
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.onRedirect(): redirect to: " +
                     redirectTo);
         }
@@ -1203,7 +1202,7 @@
             Pattern.compile("^((?:[xX]-)?[a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$");
 
     private void parseContentTypeHeader(String contentType) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.parseContentTypeHeader: " +
                     "contentType: " + contentType);
         }
@@ -1390,7 +1389,7 @@
      */
     private String guessMimeTypeFromExtension() {
         // PENDING: need to normalize url
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "guessMimeTypeFromExtension: mURL = " + mUrl);
         }
 
@@ -1425,7 +1424,7 @@
      * Cycle through our messages for synchronous loads.
      */
     /* package */ void loadSynchronousMessages() {
-        if (Config.DEBUG && !mSynchronous) {
+        if (WebView.DEBUG && !mSynchronous) {
             throw new AssertionError();
         }
         // Note: this can be called twice if it is a synchronous network load,
diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java
index 6fa0775..c9b80ce 100644
--- a/core/java/android/webkit/Network.java
+++ b/core/java/android/webkit/Network.java
@@ -20,7 +20,6 @@
 import android.net.http.*;
 import android.os.*;
 import android.util.Log;
-import android.util.Config;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -133,7 +132,7 @@
      * XXX: Must be created in the same thread as WebCore!!!!!
      */
     private Network(Context context) {
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertTrue(Thread.currentThread().
                     getName().equals(WebViewCore.THREAD_NAME));
         }
@@ -233,7 +232,7 @@
      * connecting through the proxy.
      */
     public synchronized void setProxyUsername(String proxyUsername) {
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertTrue(isValidProxySet());
         }
 
@@ -253,7 +252,7 @@
      * connecting through the proxy.
      */
     public synchronized void setProxyPassword(String proxyPassword) {
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertTrue(isValidProxySet());
         }
 
@@ -267,7 +266,7 @@
      * @return True iff succeeds.
      */
     public boolean saveState(Bundle outState) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "Network.saveState()");
         }
 
@@ -281,7 +280,7 @@
      * @return True iff succeeds.
      */
     public boolean restoreState(Bundle inState) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "Network.restoreState()");
         }
 
@@ -301,7 +300,7 @@
      * @param loader The loader that resulted in SSL errors.
      */
     public void handleSslErrorRequest(LoadListener loader) {
-        if (Config.DEBUG) Assert.assertNotNull(loader);
+        if (WebView.DEBUG) Assert.assertNotNull(loader);
         if (loader != null) {
             mSslErrorHandler.handleSslErrorRequest(loader);
         }
@@ -314,7 +313,7 @@
      * authentication request.
      */
     public void handleAuthRequest(LoadListener loader) {
-        if (Config.DEBUG) Assert.assertNotNull(loader);
+        if (WebView.DEBUG) Assert.assertNotNull(loader);
         if (loader != null) {
             mHttpAuthHandler.handleAuthRequest(loader);
         }
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 2e2fa12..5f84bbe 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -22,7 +22,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 
 import java.util.LinkedList;
@@ -121,7 +120,7 @@
      * Handles SSL error(s) on the way up to the user.
      */
     /* package */ synchronized void handleSslErrorRequest(LoadListener loader) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "SslErrorHandler.handleSslErrorRequest(): " +
                   "url=" + loader.url());
         }
@@ -158,14 +157,14 @@
 
             SslError error = loader.sslError();
 
-            if (Config.DEBUG) {
+            if (WebView.DEBUG) {
                 Assert.assertNotNull(error);
             }
 
             int primary = error.getPrimaryError();
             String host = loader.host();
 
-            if (Config.DEBUG) {
+            if (WebView.DEBUG) {
                 Assert.assertTrue(host != null && primary != 0);
             }
 
@@ -206,11 +205,11 @@
      */
     /* package */ synchronized void handleSslErrorResponse(boolean proceed) {
         LoadListener loader = mLoaderQueue.poll();
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertNotNull(loader);
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "SslErrorHandler.handleSslErrorResponse():"
                   + " proceed: " + proceed
                   + " url:" + loader.url());
@@ -222,7 +221,7 @@
                 int primary = loader.sslError().getPrimaryError();
                 String host = loader.host();
 
-                if (Config.DEBUG) {
+                if (WebView.DEBUG) {
                     Assert.assertTrue(host != null && primary != 0);
                 }
                 boolean hasKey = mSslPrefTable.containsKey(host);
diff --git a/core/java/android/webkit/StreamLoader.java b/core/java/android/webkit/StreamLoader.java
index 9098307..705157c 100644
--- a/core/java/android/webkit/StreamLoader.java
+++ b/core/java/android/webkit/StreamLoader.java
@@ -20,7 +20,6 @@
 import android.net.http.Headers;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -114,7 +113,7 @@
      * @see android.os.Handler#handleMessage(android.os.Message)
      */
     public void handleMessage(Message msg) {
-        if (Config.DEBUG && mHandler.isSynchronous()) {
+        if (WebView.DEBUG && mHandler.isSynchronous()) {
             throw new AssertionError();
         }
         switch(msg.what) {
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 0e8144e..d6ac3e9 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -23,7 +23,6 @@
 import android.net.Uri;
 import android.net.ParseException;
 import android.net.WebAddress;
-import android.util.Config;
 import android.util.Log;
 
 public final class URLUtil {
@@ -62,7 +61,7 @@
             webAddress = new WebAddress(inUrl);
         } catch (ParseException ex) {
 
-            if (Config.LOGV) {
+            if (WebView.LOGV_ENABLED) {
                 Log.v(LOGTAG, "smartUrlFilter: failed to parse url = " + inUrl);
             }
             return retVal;
diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java
index 9dea5ec..ffd6a11 100644
--- a/core/java/android/webkit/WebBackForwardList.java
+++ b/core/java/android/webkit/WebBackForwardList.java
@@ -16,7 +16,6 @@
 
 package android.webkit;
 
-import android.util.Config;
 import java.io.Serializable;
 import java.util.ArrayList;
 
@@ -138,7 +137,7 @@
         // when removing the first item, we can assert that the index is 0.
         // This lets us change the current index without having to query the
         // native BackForwardList.
-        if (Config.DEBUG && (index != 0)) {
+        if (WebView.DEBUG && (index != 0)) {
             throw new AssertionError();
         }
         final WebHistoryItem h = mArray.remove(index);
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 025e6bb..105eacd 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1097,7 +1097,7 @@
     /*package*/
     synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
         mBrowserFrame = frame;
-        if (android.util.Config.DEBUG) {
+        if (WebView.DEBUG) {
             junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
         }
         nativeSync(frame.mNativeFrame);
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index e6e9994..ded17ed 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -21,7 +21,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
-import android.util.Config;
 import android.util.Log;
 
 abstract class WebSyncManager implements Runnable {
@@ -48,7 +47,7 @@
         @Override
         public void handleMessage(Message msg) {
             if (msg.what == SYNC_MESSAGE) {
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "*** WebSyncManager sync ***");
                 }
                 syncFromRamToFlash();
@@ -95,7 +94,7 @@
      * sync() forces sync manager to sync now
      */
     public void sync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "*** WebSyncManager sync ***");
         }
         if (mHandler == null) {
@@ -110,7 +109,7 @@
      * resetSync() resets sync manager's timer
      */
     public void resetSync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "*** WebSyncManager resetSync ***");
         }
         if (mHandler == null) {
@@ -125,7 +124,7 @@
      * startSync() requests sync manager to start sync
      */
     public void startSync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "***  WebSyncManager startSync ***, Ref count:" + 
                     mStartSyncRefCount);
         }
@@ -143,7 +142,7 @@
      * the queue to break the sync loop
      */
     public void stopSync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "*** WebSyncManager stopSync ***, Ref count:" + 
                     mStartSyncRefCount);
         }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index a5846ed..a926355 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -42,7 +42,6 @@
 import android.text.Selection;
 import android.text.Spannable;
 import android.util.AttributeSet;
-import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Gravity;
@@ -110,7 +109,7 @@
     // keep debugging parameters near the top of the file
     static final String LOGTAG = "webview";
     static final boolean DEBUG = false;
-    static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean LOGV_ENABLED = DEBUG;
 
     private class ExtendedZoomControls extends FrameLayout {
         public ExtendedZoomControls(Context context, AttributeSet attrs) {
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 72b30f6..58d8ae7 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -29,7 +29,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
-import android.util.Config;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.KeyEvent;
@@ -43,7 +42,7 @@
 
     private static final String LOGTAG = "webcore";
     static final boolean DEBUG = false;
-    static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean LOGV_ENABLED = DEBUG;
 
     static {
         // Load libwebcore during static initialization. This happens in the
diff --git a/core/java/android/webkit/gears/AndroidRadioDataProvider.java b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
index c920d45..2d431a8 100644
--- a/core/java/android/webkit/gears/AndroidRadioDataProvider.java
+++ b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
@@ -46,6 +46,9 @@
   private static final int RADIO_TYPE_UNKNOWN = 0;
   private static final int RADIO_TYPE_GSM = 1;
   private static final int RADIO_TYPE_WCDMA = 2;
+  private static final int RADIO_TYPE_CDMA = 3;
+  private static final int RADIO_TYPE_EVDO = 4;
+  private static final int RADIO_TYPE_1xRTT = 5;
 
   /** Simple container for radio data */
   public static final class RadioData {
@@ -102,12 +105,21 @@
       }
 
       // Finally get the radio type.
+      //TODO We have to edit the parameter for getNetworkType regarding CDMA
       int type = telephonyManager.getNetworkType();
       if (type == TelephonyManager.NETWORK_TYPE_UMTS) {
         radioData.radioType = RADIO_TYPE_WCDMA;
       } else if (type == TelephonyManager.NETWORK_TYPE_GPRS
                  || type == TelephonyManager.NETWORK_TYPE_EDGE) {
         radioData.radioType = RADIO_TYPE_GSM;
+      } else if (type == TelephonyManager.NETWORK_TYPE_CDMA) {
+          radioData.radioType = RADIO_TYPE_CDMA;
+      } else if (type == TelephonyManager.NETWORK_TYPE_EVDO_0) {
+          radioData.radioType = RADIO_TYPE_EVDO;
+      } else if (type == TelephonyManager.NETWORK_TYPE_EVDO_A) {
+          radioData.radioType = RADIO_TYPE_EVDO;
+      } else if (type == TelephonyManager.NETWORK_TYPE_1xRTT) {
+          radioData.radioType = RADIO_TYPE_1xRTT;
       }
 
       // Print out what we got.
diff --git a/core/java/android/webkit/gears/AndroidWifiDataProvider.java b/core/java/android/webkit/gears/AndroidWifiDataProvider.java
index 7379f59..d2850b06 100644
--- a/core/java/android/webkit/gears/AndroidWifiDataProvider.java
+++ b/core/java/android/webkit/gears/AndroidWifiDataProvider.java
@@ -33,7 +33,6 @@
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.os.Looper;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.WebView;
 import java.util.List;
@@ -48,6 +47,11 @@
    */
   private static final String TAG = "Gears-J-WifiProvider";
   /**
+   * Flag for guarding Log.v() calls.
+   * Set to true to enable extra debug logging.
+   */
+  private static final boolean LOGV_ENABLED = false;
+  /**
    * Our Wifi manager instance.
    */
   private WifiManager mWifiManager;
@@ -104,7 +108,7 @@
    */
   public void shutdown() {
     mContext.unregisterReceiver(this);
-    if (Config.LOGV) {
+    if (LOGV_ENABLED) {
       Log.v(TAG, "Wifi provider closed.");
     }
   }
@@ -118,7 +122,7 @@
   public void onReceive(Context context, Intent intent) {
     if (intent.getAction().equals(
             mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-      if (Config.LOGV) {
+      if (LOGV_ENABLED) {
         Log.v(TAG, "Wifi scan resulst available");
       }
       onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject);
diff --git a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
index 529e666..74d27ed 100644
--- a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
+++ b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
@@ -29,7 +29,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CacheManager;
 import android.webkit.CacheManager.CacheResult;
@@ -88,6 +87,8 @@
 public final class ApacheHttpRequestAndroid {
     /** Debug logging tag. */
     private static final String LOG_TAG = "Gears-J";
+    /** Flag for guarding Log.v() calls. */
+    private static final boolean LOGV_ENABLED = false;
     /** HTTP response header line endings are CR-LF style. */
     private static final String HTTP_LINE_ENDING = "\r\n";
     /** Safe MIME type to use whenever it isn't specified. */
@@ -173,18 +174,18 @@
         public void run() {
             boolean problem = false;
             try {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "REQUEST : " + mMethod.getRequestLine());
                 }
                 mResponse = mClient.execute(mMethod);
                 if (mResponse != null) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "response (status line): "
                               + mResponse.getStatusLine());
                     }
                     mResponseLine = "" + mResponse.getStatusLine();
                 } else {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "problem, response == null");
                     }
                     problem = true;
@@ -198,7 +199,7 @@
             }
 
             if (!problem) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "Request complete ("
                           + mMethod.getRequestLine() + ")");
                 }
@@ -206,7 +207,7 @@
                 mConnectionFailedLock.lock();
                 mConnectionFailed = true;
                 mConnectionFailedLock.unlock();
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "Request FAILED ("
                           + mMethod.getRequestLine() + ")");
                 }
@@ -233,7 +234,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "InterruptedException while putting " +
                             "a DataPacket in the Buffer: " + e);
                     }
@@ -248,7 +249,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                       Log.i(LOG_TAG, "InterruptedException while getting " +
                           "a DataPacket in the Buffer: " + e);
                     }
@@ -271,7 +272,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "InterruptedException while waiting " +
                             "until a DataPacket is consumed: " + e);
                     }
@@ -285,7 +286,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "InterruptedException while indicating "
                               + "that the DataPacket has been consumed: " + e);
                     }
@@ -373,14 +374,14 @@
                 mSignal.packetConsumed();
                 mConnectionFailedLock.lock();
                 if (mConnectionFailed) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "stopping loop on error");
                     }
                     finished = true;
                 }
                 mConnectionFailedLock.unlock();
             }
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "flushing the outputstream...");
             }
             mOutputStream.flush();
@@ -399,7 +400,7 @@
         private void write(DataPacket packet) {
             try {
                 if (mOutputStream == null) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "NO OUTPUT STREAM !!!");
                     }
                     return;
@@ -407,7 +408,7 @@
                 mOutputStream.write(packet.getBytes(), 0, packet.getLength());
                 mOutputStream.flush();
             } catch (IOException e) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "exc: " + e);
                 }
                 mConnectionFailedLock.lock();
@@ -423,7 +424,7 @@
                     mStreamingReady.await();
                 }
             } catch (InterruptedException e) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "InterruptedException in "
                           + "StreamEntity::isReady() : ", e);
                 }
@@ -468,7 +469,7 @@
      *                  False on failure.
      */
     public synchronized boolean open(String method, String url) {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "open " + method + " " + url);
         }
         // Create the client
@@ -502,7 +503,7 @@
         } else if ("DELETE".equalsIgnoreCase(method)) {
             mMethod = new HttpDelete(url);
         } else {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Method " + method + " not supported");
             }
             return false;
@@ -549,7 +550,7 @@
      * (unless already finished)
      */
     private void waitUntilConnectionFinished() {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "waitUntilConnectionFinished("
                   + mConnectionFinished + ")");
         }
@@ -558,11 +559,11 @@
                 try {
                     mHttpThread.join();
                     mConnectionFinished = true;
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "http thread joined");
                     }
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "interrupted: " + e);
                     }
                 }
@@ -596,7 +597,7 @@
         Header[] headers = mResponse.getAllHeaders();
         for (int i = 0; i < headers.length; i++) {
             Header header = headers[i];
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "header " + header.getName()
                       + " -> " + header.getValue());
             }
@@ -615,7 +616,7 @@
      */
     public synchronized void setRequestHeader(String name, String value) {
         String[] mapValue = { name, value };
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "setRequestHeader: " + name + " => " + value);
         }
         if (name.equalsIgnoreCase(KEY_CONTENT_LENGTH)) {
@@ -647,7 +648,7 @@
         while (it.hasNext()) {
             // Set the key case-sensitive.
             String[] entry = it.next();
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "apply header " + entry[HEADERS_MAP_INDEX_KEY] +
                     " => " + entry[HEADERS_MAP_INDEX_VALUE]);
             }
@@ -671,7 +672,7 @@
                 return null;
             }
         } else {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "getResponseHeader() called but "
                       + "response not received");
             }
@@ -687,7 +688,7 @@
      */
     public synchronized String getAllResponseHeaders() {
         if (mResponseHeaders == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "getAllResponseHeaders() called but "
                       + "response not received");
             }
@@ -715,7 +716,7 @@
      * @param value The associated value.
      */
     private void setResponseHeader(String name, String value) {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Set response header " + name + ": " + value);
         }
         String mapValue[] = { name, value };
@@ -766,7 +767,7 @@
         UrlInterceptHandlerGears.ServiceResponse serviceResponse =
             handler.getServiceResponse(url, mRequestHeaders);
         if (serviceResponse == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "No response in LocalServer");
             }
             return false;
@@ -776,7 +777,7 @@
         mBodyInputStream = serviceResponse.getInputStream();
         mResponseLine = serviceResponse.getStatusLine();
         mResponseHeaders = serviceResponse.getResponseHeaders();
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Got response from LocalServer: " + mResponseLine);
         }
         return true;
@@ -803,19 +804,19 @@
         CacheResult mCacheResult =
             CacheManager.getCacheFile(url, cacheRequestHeaders);
         if (mCacheResult == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "No CacheResult for " + url);
             }
             return false;
         }
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Got CacheResult from browser cache");
         }
         // Check for expiry. -1 is "never", otherwise milliseconds since 1970.
         // Can be compared to System.currentTimeMillis().
         long expires = mCacheResult.getExpires();
         if (expires >= 0 && System.currentTimeMillis() >= expires) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "CacheResult expired "
                     + (System.currentTimeMillis() - expires)
                     + " milliseconds ago");
@@ -827,7 +828,7 @@
         mBodyInputStream = mCacheResult.getInputStream();
         if (mBodyInputStream == null) {
             // Cache result may have gone away.
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "No mBodyInputStream for CacheResult " + url);
             }
             return false;
@@ -855,7 +856,7 @@
         }
         // Synthesize the response line.
         mResponseLine = "HTTP/1.1 " + statusCode + " " + statusMessage;
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Synthesized " + mResponseLine);
         }
         // Synthesize the returned headers from cache.
@@ -914,7 +915,7 @@
      */
     public synchronized boolean createCacheResult(
         String url, int responseCode, String mimeType, String encoding) {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Making cache entry for " + url);
         }
         // Take the headers and parse them into a format needed by
@@ -935,14 +936,14 @@
         mCacheResult = CacheManager.createCacheFile(
             url, responseCode, cacheHeaders, mimeType, true);
         if (mCacheResult != null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Saving into cache");
             }
             mCacheResult.setEncoding(encoding);
             mCacheResultUrl = url;
             return true;
         } else {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Couldn't create mCacheResult");
             }
             return false;
@@ -960,7 +961,7 @@
      */
     public synchronized boolean appendCacheResult(byte[] data, int bytes) {
         if (mCacheResult == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "appendCacheResult() called without a "
                       + "CacheResult initialized");
             }
@@ -969,7 +970,7 @@
         try {
             mCacheResult.getOutputStream().write(data, 0, bytes);
         } catch (IOException ex) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Got IOException writing cache data: " + ex);
             }
             return false;
@@ -984,14 +985,14 @@
      */
     public synchronized boolean saveCacheResult() {
         if (mCacheResult == null || mCacheResultUrl == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Tried to save cache result but "
                       + "createCacheResult not called");
             }
             return false;
         }
 
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Saving cache result");
         }
         CacheManager.saveCacheFile(mCacheResultUrl, mCacheResult);
@@ -1006,7 +1007,7 @@
      * ability to receive a null packet for sendPostData().
      */
     public synchronized void abort() {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "ABORT CALLED");
         }
         if (mMethod != null) {
@@ -1019,7 +1020,7 @@
      * thread to complete.
      */
     public synchronized void interrupt() {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "INTERRUPT CALLED");
         }
         mConnectionFailedLock.lock();
@@ -1053,7 +1054,7 @@
                     mBodyInputStream = entity.getContent();
                 }
             } catch (IOException inputException) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "Failed to connect InputStream: "
                           + inputException);
                 }
@@ -1062,7 +1063,7 @@
             }
             if (mBodyInputStream == null) {
                 // No error stream either. Treat as a 0 byte response.
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "No InputStream");
                 }
                 return 0; // EOF.
@@ -1081,7 +1082,7 @@
             }
         } catch (IOException e) {
             // An abort() interrupts us by calling close() on our stream.
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Got IOException in mBodyInputStream.read(): ", e);
             }
             ret = -1;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 772ad89..b408f27 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -983,18 +983,6 @@
         mSelectorRect.setEmpty();
         invalidate();
     }
-    
-    /**
-     * The list is empty and we need to change the layout, so *really* clear everything out.
-     * @hide - for AutoCompleteTextView & SearchDialog only
-     */
-    /* package */ void resetListAndClearViews() {
-        rememberSyncState();
-        removeAllViewsInLayout();
-        mRecycler.clear();
-        mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
-        requestLayout();
-    }
 
     @Override
     protected int computeVerticalScrollExtent() {
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index dfb971e..1e122a7 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -110,6 +110,10 @@
     private final DropDownItemClickListener mDropDownItemClickListener =
             new DropDownItemClickListener();
 
+    private boolean mDropDownAlwaysVisible = false;
+
+    private boolean mDropDownDismissedOnCompletion = true;
+
     private int mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;
     private boolean mOpenBefore;
 
@@ -123,6 +127,8 @@
     // The widget is attached to a window when mAttachCount > 0
     private int mAttachCount;
 
+    private AutoCompleteTextView.PassThroughClickListener mPassThroughClickListener;
+
     public AutoCompleteTextView(Context context) {
         this(context, null);
     }
@@ -182,6 +188,28 @@
         setFocusable(true);
 
         addTextChangedListener(new MyWatcher());
+
+        mPassThroughClickListener = new PassThroughClickListener();
+        super.setOnClickListener(mPassThroughClickListener);
+    }
+
+    @Override
+    public void setOnClickListener(OnClickListener listener) {
+        mPassThroughClickListener.mWrapped = listener;
+    }
+
+    /**
+     * Private hook into the on click event, dispatched from {@link PassThroughClickListener}
+     */
+    private void onClickImpl() {
+        // if drop down should always visible, bring it back in front of the soft
+        // keyboard when the user touches the text field
+        if (mDropDownAlwaysVisible
+                && mPopup.isShowing()
+                && mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) {
+            mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
+            mPopup.update();
+        }
     }
 
     /**
@@ -211,6 +239,8 @@
      * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p>
      * 
      * @return the width for the drop down list
+     * 
+     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth
      */
     public int getDropDownWidth() {
         return mDropDownWidth;
@@ -222,6 +252,8 @@
      * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p>
      * 
      * @param width the width to use
+     * 
+     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth
      */
     public void setDropDownWidth(int width) {
         mDropDownWidth = width;
@@ -231,6 +263,8 @@
      * <p>Returns the id for the view that the auto-complete drop down list is anchored to.</p>
      *  
      * @return the view's id, or {@link View#NO_ID} if none specified
+     * 
+     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor
      */
     public int getDropDownAnchor() {
         return mDropDownAnchorId;
@@ -242,13 +276,173 @@
      * loading a view which is not yet instantiated.</p>
      * 
      * @param id the id to anchor the drop down list view to
+     * 
+     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor 
      */
     public void setDropDownAnchor(int id) {
         mDropDownAnchorId = id;
         mDropDownAnchorView = null;
     }
+    
+    /**
+     * <p>Gets the background of the auto-complete drop-down list.</p>
+     * 
+     * @return the background drawable
+     * 
+     * @attr ref android.R.styleable#PopupWindow_popupBackground
+     *
+     * @hide Pending API council approval
+     */
+    public Drawable getDropDownBackground() {
+        return mPopup.getBackground();
+    }
+    
+    /**
+     * <p>Sets the background of the auto-complete drop-down list.</p>
+     * 
+     * @param d the drawable to set as the background
+     * 
+     * @attr ref android.R.styleable#PopupWindow_popupBackground
+     *
+     * @hide Pending API council approval
+     */
+    public void setDropDownBackgroundDrawable(Drawable d) {
+        mPopup.setBackgroundDrawable(d);
+    }
+    
+    /**
+     * <p>Sets the background of the auto-complete drop-down list.</p>
+     * 
+     * @param id the id of the drawable to set as the background
+     * 
+     * @attr ref android.R.styleable#PopupWindow_popupBackground
+     *
+     * @hide Pending API council approval
+     */
+    public void setDropDownBackgroundResource(int id) {
+        mPopup.setBackgroundDrawable(getResources().getDrawable(id));
+    }
 
     /**
+     * <p>Sets the animation style of the auto-complete drop-down list.</p>
+     *
+     * <p>If the drop-down is showing, calling this method will take effect only
+     * the next time the drop-down is shown.</p>
+     *
+     * @param animationStyle animation style to use when the drop-down appears
+     *      and disappears.  Set to -1 for the default animation, 0 for no
+     *      animation, or a resource identifier for an explicit animation.
+     *
+     * @hide Pending API council approval
+     */
+    public void setDropDownAnimationStyle(int animationStyle) {
+        mPopup.setAnimationStyle(animationStyle);
+    }
+
+    /**
+     * <p>Returns the animation style that is used when the drop-down list appears and disappears
+     * </p>
+     *
+     * @return the animation style that is used when the drop-down list appears and disappears
+     *
+     * @hide Pending API council approval
+     */
+    public int getDropDownAnimationStyle() {
+        return mPopup.getAnimationStyle();
+    }
+    
+    /**
+     * <p>Sets the vertical offset used for the auto-complete drop-down list.</p>
+     * 
+     * @param offset the vertical offset
+     *
+     * @hide Pending API council approval
+     */
+    public void setDropDownVerticalOffset(int offset) {
+        mDropDownVerticalOffset = offset;
+    }
+    
+    /**
+     * <p>Gets the vertical offset used for the auto-complete drop-down list.</p>
+     * 
+     * @return the vertical offset
+     *
+     * @hide Pending API council approval
+     */
+    public int getDropDownVerticalOffset() {
+        return mDropDownVerticalOffset;
+    }
+    
+    /**
+     * <p>Sets the horizontal offset used for the auto-complete drop-down list.</p>
+     * 
+     * @param offset the horizontal offset
+     *
+     * @hide Pending API council approval
+     */
+    public void setDropDownHorizontalOffset(int offset) {
+        mDropDownHorizontalOffset = offset;
+    }
+    
+    /**
+     * <p>Gets the horizontal offset used for the auto-complete drop-down list.</p>
+     * 
+     * @return the horizontal offset
+     *
+     * @hide Pending API council approval
+     */
+    public int getDropDownHorizontalOffset() {
+        return mDropDownHorizontalOffset;
+    }
+
+    /**
+     * @return Whether the drop-down is visible as long as there is {@link #enoughToFilter()}
+     *
+     * @hide Pending API council approval
+     */
+    public boolean isDropDownAlwaysVisible() {
+        return mDropDownAlwaysVisible;
+    }
+
+    /**
+     * Sets whether the drop-down should remain visible as long as there is there is
+     * {@link #enoughToFilter()}.  This is useful if an unknown number of results are expected
+     * to show up in the adapter sometime in the future.
+     *
+     * The drop-down will occupy the entire screen below {@link #getDropDownAnchor} regardless
+     * of the size or content of the list.  {@link #getDropDownBackground()} will fill any space
+     * that is not used by the list.
+     *
+     * @param dropDownAlwaysVisible Whether to keep the drop-down visible.
+     *
+     * @hide Pending API council approval
+     */
+    public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
+        mDropDownAlwaysVisible = dropDownAlwaysVisible;
+    }
+   
+    /**
+     * Checks whether the drop-down is dismissed when a suggestion is clicked.
+     * 
+     * @hide Pending API council approval
+     */
+    public boolean isDropDownDismissedOnCompletion() {
+        return mDropDownDismissedOnCompletion;
+    }
+    
+    /**
+     * Sets whether the drop-down is dismissed when a suggestion is clicked. This is 
+     * true by default.
+     * 
+     * @param dropDownDismissedOnCompletion Whether to dismiss the drop-down.
+     * 
+     * @hide Pending API council approval
+     */
+    public void setDropDownDismissedOnCompletion(boolean dropDownDismissedOnCompletion) {
+        mDropDownDismissedOnCompletion = dropDownDismissedOnCompletion;
+    }
+ 
+    /**
      * <p>Returns the number of characters the user must type before the drop
      * down list is shown.</p>
      *
@@ -628,16 +822,6 @@
         }
         return ListView.INVALID_POSITION;
     }
-    
-    /**
-     * We're changing the adapter and its views so really, really clear everything out
-     * @hide - for SearchDialog only
-     */
-    public void resetListAndClearViews() {
-        if (mDropDownList != null) {
-            mDropDownList.resetListAndClearViews();
-        }
-    }
 
     /**
      * <p>Starts filtering the content of the drop down list. The filtering
@@ -709,7 +893,9 @@
             }
         }
 
-        dismissDropDown();
+        if (mDropDownDismissedOnCompletion) {
+            dismissDropDown();
+        }
     }
     
     /**
@@ -721,6 +907,42 @@
     }
 
     /**
+     * Like {@link #setText(CharSequence)}, except that it can disable filtering.
+     *
+     * @param filter If <code>false</code>, no filtering will be performed
+     *        as a result of this call.
+     * 
+     * @hide Pending API council approval.
+     */
+    public void setText(CharSequence text, boolean filter) {
+        if (filter) {
+            setText(text);
+        } else {
+            mBlockCompletion = true;
+            setText(text);
+            mBlockCompletion = false;
+        }
+    }
+    
+    /**
+     * Like {@link #setTextKeepState(CharSequence)}, except that it can disable filtering.
+     *
+     * @param filter If <code>false</code>, no filtering will be performed
+     *        as a result of this call.
+     * 
+     * @hide Pending API council approval.
+     */
+    public void setTextKeepState(CharSequence text, boolean filter) {
+        if (filter) {
+            setTextKeepState(text);
+        } else {
+            mBlockCompletion = true;
+            setTextKeepState(text);
+            mBlockCompletion = false;
+        }
+    }
+    
+    /**
      * <p>Performs the text completion by replacing the current text by the
      * selected item. Subclasses should override this method to avoid replacing
      * the whole content of the edit box.</p>
@@ -734,6 +956,7 @@
         Selection.setSelection(spannable, spannable.length());
     }
 
+    /** {@inheritDoc} */
     public void onFilterComplete(int count) {
         if (mAttachCount <= 0) return;
 
@@ -744,7 +967,7 @@
          * to filter.
          */
 
-        if (count > 0 && enoughToFilter()) {
+        if ((count > 0 || mDropDownAlwaysVisible) && enoughToFilter()) {
             if (hasFocus() && hasWindowFocus()) {
                 showDropDown();
             }
@@ -809,22 +1032,6 @@
     }
     
     /**
-     * Set the horizontal offset with respect to {@link #setDropDownAnchor(int)}
-     * @hide pending API council review
-     */
-    public void setDropDownHorizontalOffset(int horizontalOffset) {
-        mDropDownHorizontalOffset = horizontalOffset;
-    }
-    
-    /**
-     * Set the vertical offset with respect to {@link #setDropDownAnchor(int)}
-     * @hide pending API council review
-     */
-    public void setDropDownVerticalOffset(int verticalOffset) {
-        mDropDownVerticalOffset = verticalOffset;
-    }
-
-    /**
      * <p>Used for lazy instantiation of the anchor view from the id we have. If the value of
      * the id is NO_ID or we can't find a view for the given id, we return this TextView as
      * the default anchoring point.</p>
@@ -856,10 +1063,9 @@
                     mDropDownVerticalOffset, widthSpec, height);
         } else {
             if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
-                mPopup.setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT,
-                        ViewGroup.LayoutParams.WRAP_CONTENT);
+                mPopup.setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT, 0);
             } else {
-                mPopup.setWindowLayoutMode(0, ViewGroup.LayoutParams.WRAP_CONTENT);
+                mPopup.setWindowLayoutMode(0, 0);
                 if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
                     mPopup.setWidth(getDropDownAnchorView().getWidth());
                 } else {
@@ -868,7 +1074,10 @@
             }
             mPopup.setHeight(height);
             mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
-            mPopup.setOutsideTouchable(true);
+            
+            // use outside touchable to dismiss drop down when touching outside of it, so
+            // only set this if the dropdown is not always visible
+            mPopup.setOutsideTouchable(!mDropDownAlwaysVisible);
             mPopup.setTouchInterceptor(new PopupTouchIntercepter());
             mPopup.showAsDropDown(getDropDownAnchorView(),
                     mDropDownHorizontalOffset, mDropDownVerticalOffset);
@@ -966,8 +1175,10 @@
         final int maxHeight = mPopup.getMaxAvailableHeight(this, mDropDownVerticalOffset);
         //otherHeights += dropDownView.getPaddingTop() + dropDownView.getPaddingBottom();
 
-        return mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
+        final int measuredHeight = mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
                 0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights;
+
+        return mDropDownAlwaysVisible ? maxHeight : measuredHeight;
     }
 
     private View getHintView(Context context) {
@@ -1183,4 +1394,21 @@
          */
         CharSequence fixText(CharSequence invalidText);
     }
+
+    /**
+     * Allows us a private hook into the on click event without preventing users from setting
+     * their own click listener.
+     */
+    private class PassThroughClickListener implements OnClickListener {
+
+        private View.OnClickListener mWrapped;
+
+        /** {@inheritDoc} */
+        public void onClick(View v) {
+            onClickImpl();
+
+            if (mWrapped != null) mWrapped.onClick(v);
+        }
+    }
+
 }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index a786b3f..1daee4e 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1394,6 +1394,11 @@
                 resetList();
                 invokeOnItemScrollListener();
                 return;
+            } else if (mItemCount != mAdapter.getCount()) {
+                throw new IllegalStateException("The content of the adapter has changed but "
+                        + "ListView did not receive a notification. Make sure the content of "
+                        + "your adapter is not modified from a background thread, but only "
+                        + "from the UI thread.");
             }
 
             setSelectedPositionInt(mNextSelectedPosition);
@@ -3215,6 +3220,29 @@
     }
 
     /**
+     * Returns the set of checked items ids. The result is only valid if
+     * the choice mode has not been set to {@link #CHOICE_MODE_SINGLE}.
+     *
+     * @return A new array which contains the id of each checked item in the list.
+     */
+    public long[] getCheckItemIds() {
+        if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null && mAdapter != null) {
+            final SparseBooleanArray states = mCheckStates;
+            final int count = states.size();
+            final long[] ids = new long[count];
+            final ListAdapter adapter = mAdapter;
+
+            for (int i = 0; i < count; i++) {
+                ids[i]= adapter.getItemId(states.keyAt(i));
+            }
+
+            return ids;
+        }
+
+        return new long[0];
+    }
+
+    /**
      * Clear any choices previously set
      */
     public void clearChoices() {
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index b162a0e..0c9d980 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -444,27 +444,55 @@
         updatePausePlay();
     }
 
+    // There are two scenarios that can trigger the seekbar listener to trigger:
+    //
+    // The first is the user using the touchpad to adjust the posititon of the
+    // seekbar's thumb. In this case onStartTrackingTouch is called followed by
+    // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
+    // We're setting the field "mDragging" to true for the duration of the dragging
+    // session to avoid jumps in the position in case of ongoing playback.
+    //
+    // The second scenario involves the user operating the scroll ball, in this
+    // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
+    // we will simply apply the updated position without suspending regular updates.
     private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
-        long duration;
         public void onStartTrackingTouch(SeekBar bar) {
             show(3600000);
-            duration = mPlayer.getDuration();
+
+            mDragging = true;
+
+            // By removing these pending progress messages we make sure
+            // that a) we won't update the progress while the user adjusts
+            // the seekbar and b) once the user is done dragging the thumb
+            // we will post one of these messages to the queue again and
+            // this ensures that there will be exactly one message queued up.
+            mHandler.removeMessages(SHOW_PROGRESS);
         }
-        public void onProgressChanged(SeekBar bar, int progress, boolean fromtouch) {
-            if (fromtouch) {
-                mDragging = true;
-                duration = mPlayer.getDuration();
-                long newposition = (duration * progress) / 1000L;
-                mPlayer.seekTo( (int) newposition);
-                if (mCurrentTime != null)
-                    mCurrentTime.setText(stringForTime( (int) newposition));
+
+        public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
+            if (!fromuser) {
+                // We're not interested in programmatically generated changes to
+                // the progress bar's position.
+                return;
             }
+
+            long duration = mPlayer.getDuration();
+            long newposition = (duration * progress) / 1000L;
+            mPlayer.seekTo( (int) newposition);
+            if (mCurrentTime != null)
+                mCurrentTime.setText(stringForTime( (int) newposition));
         }
+
         public void onStopTrackingTouch(SeekBar bar) {
             mDragging = false;
             setProgress();
             updatePausePlay();
             show(sDefaultTimeout);
+
+            // Ensure that progress is properly updated in the future,
+            // the call to show() does not guarantee this because it is a
+            // no-op if we are already showing.
+            mHandler.sendEmptyMessage(SHOW_PROGRESS);
         }
     };
 
diff --git a/core/java/android/widget/SimpleCursorAdapter.java b/core/java/android/widget/SimpleCursorAdapter.java
index c1595ea..c1bcd42 100644
--- a/core/java/android/widget/SimpleCursorAdapter.java
+++ b/core/java/android/widget/SimpleCursorAdapter.java
@@ -145,17 +145,17 @@
         for (int i = 0; i < count; i++) {
             final View v = holder[i];
             if (v != null) {
-                String text = cursor.getString(from[i]);
-                if (text == null) {
-                    text = "";
-                }
-
                 boolean bound = false;
                 if (binder != null) {
                     bound = binder.setViewValue(v, cursor, from[i]);
                 }
 
                 if (!bound) {
+                    String text = cursor.getString(from[i]);
+                    if (text == null) {
+                        text = "";
+                    }
+
                     if (v instanceof TextView) {
                         setViewText((TextView) v, text);
                     } else if (v instanceof ImageView) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9c810e1..de0c982 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1641,6 +1641,7 @@
     @android.view.RemotableViewMethod
     public void setTextScaleX(float size) {
         if (size != mTextPaint.getTextScaleX()) {
+            mUserSetTextScaleX = true;
             mTextPaint.setTextScaleX(size);
 
             if (mLayout != null) {
@@ -2511,6 +2512,8 @@
             text = "";
         }
 
+        if (!mUserSetTextScaleX) mTextPaint.setTextScaleX(1.0f);
+
         if (text instanceof Spanned &&
             ((Spanned) text).getSpanStart(TextUtils.TruncateAt.MARQUEE) >= 0) {
             setHorizontalFadingEdgeEnabled(true);
@@ -3920,6 +3923,11 @@
 
         layout.draw(canvas, highlight, mHighlightPaint, voffsetCursor - voffsetText);
 
+        if (mMarquee != null && mMarquee.shouldDrawGhost()) {
+            canvas.translate((int) mMarquee.getGhostOffset(), 0.0f);
+            layout.draw(canvas, highlight, mHighlightPaint, voffsetCursor - voffsetText);
+        }
+
         /*  Comment out until we decide what to do about animations
         if (currentTransformation != null) {
             mTextPaint.setLinearTextOn(isLinearTextOn);
@@ -4814,18 +4822,39 @@
         }
 
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
-            final int height = mLayoutParams.height;
-            // If the size of the view does not depend on the size of the text, try to
-            // start the marquee immediately
-            if (height != LayoutParams.WRAP_CONTENT && height != LayoutParams.FILL_PARENT) {
-                startMarquee();
-            } else {
-                // Defer the start of the marquee until we know our width (see setFrame())
-                mRestartMarquee = true;
+            if (!compressText(ellipsisWidth)) {
+                final int height = mLayoutParams.height;
+                // If the size of the view does not depend on the size of the text, try to
+                // start the marquee immediately
+                if (height != LayoutParams.WRAP_CONTENT && height != LayoutParams.FILL_PARENT) {
+                    startMarquee();
+                } else {
+                    // Defer the start of the marquee until we know our width (see setFrame())
+                    mRestartMarquee = true;
+                }
             }
         }
     }
 
+    private boolean compressText(float width) {
+        if (width > 0.0f && mLayout != null && getLineCount() == 1 && !mUserSetTextScaleX) {
+            final float textWidth = mLayout.getLineWidth(0);
+            final float overflow = (textWidth - width) / width;
+
+            if (overflow > 0.0f && overflow <= Marquee.MARQUEE_DELTA_MAX) {
+                mTextPaint.setTextScaleX(1.0f - overflow - 0.005f);
+                post(new Runnable() {
+                    public void run() {
+                        requestLayout();
+                    }
+                });
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     private static int desired(Layout layout) {
         int n = layout.getLineCount();
         CharSequence text = layout.getText();
@@ -5683,8 +5712,13 @@
     }
 
     private void startMarquee() {
+        if (compressText(getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight())) {
+            return;
+        }
+
         if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected()) &&
                 getLineCount() == 1 && canMarquee()) {
+
             if (mMarquee == null) mMarquee = new Marquee(this);
             mMarquee.start(mMarqueeRepeatLimit);
         }
@@ -5708,6 +5742,7 @@
 
     private static final class Marquee extends Handler {
         // TODO: Add an option to configure this
+        private static final float MARQUEE_DELTA_MAX = 0.07f;
         private static final int MARQUEE_DELAY = 1200;
         private static final int MARQUEE_RESTART_DELAY = 1200;
         private static final int MARQUEE_RESOLUTION = 1000 / 30;
@@ -5726,6 +5761,10 @@
         private byte mStatus = MARQUEE_STOPPED;
         private float mScrollUnit;
         private float mMaxScroll;
+        float mMaxFadeScroll;
+        private float mGhostStart;
+        private float mGhostOffset;
+        private float mFadeStop;
         private int mRepeatLimit;
 
         float mScroll;
@@ -5801,13 +5840,32 @@
             if (textView != null && textView.mLayout != null) {
                 mStatus = MARQUEE_STARTING;
                 mScroll = 0.0f;
-                mMaxScroll = textView.mLayout.getLineWidth(0) - (textView.getWidth() -
-                        textView.getCompoundPaddingLeft() - textView.getCompoundPaddingRight());
+                final int textWidth = textView.getWidth() - textView.getCompoundPaddingLeft() -
+                        textView.getCompoundPaddingRight();
+                final float lineWidth = textView.mLayout.getLineWidth(0);
+                mGhostStart = lineWidth - textWidth + textWidth / 3.0f;
+                mMaxScroll = mGhostStart + textWidth;
+                mGhostOffset = lineWidth + textWidth / 3.0f;
+                mFadeStop = lineWidth + textWidth / 6.0f;
+                mMaxFadeScroll = mGhostStart + lineWidth + lineWidth;
+
                 textView.invalidate();
                 sendEmptyMessageDelayed(MESSAGE_START, MARQUEE_DELAY);
             }
         }
 
+        float getGhostOffset() {
+            return mGhostOffset;
+        }
+
+        boolean shouldDrawLeftFade() {
+            return mScroll <= mFadeStop;
+        }
+
+        boolean shouldDrawGhost() {
+            return mStatus == MARQUEE_RUNNING && mScroll > mGhostStart;
+        }
+
         boolean isRunning() {
             return mStatus == MARQUEE_RUNNING;
         }
@@ -6433,7 +6491,11 @@
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
             if (mMarquee != null && !mMarquee.isStopped()) {
                 final Marquee marquee = mMarquee;
-                return marquee.mScroll / getHorizontalFadingEdgeLength();
+                if (marquee.shouldDrawLeftFade()) {
+                    return marquee.mScroll / getHorizontalFadingEdgeLength();
+                } else {
+                    return 0.0f;
+                }
             } else if (getLineCount() == 1) {
                 switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
@@ -6455,7 +6517,7 @@
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
             if (mMarquee != null && !mMarquee.isStopped()) {
                 final Marquee marquee = mMarquee;
-                return (marquee.mMaxScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
+                return (marquee.mMaxFadeScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
             } else if (getLineCount() == 1) {
                 switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
@@ -6994,7 +7056,8 @@
     private ArrayList<TextWatcher>  mListeners = null;
 
     // display attributes
-    private TextPaint mTextPaint;
+    private TextPaint               mTextPaint;
+    private boolean                 mUserSetTextScaleX;
     private Paint                   mHighlightPaint;
     private int                     mHighlightColor = 0xFFBBDDFF;
     private Layout                  mLayout;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index bb0c912..9ce532c 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -46,6 +46,7 @@
     void noteScanWifiLockAcquired(int uid);
     void noteScanWifiLockReleased(int uid);
     void setOnBattery(boolean onBattery, int level);
+    void recordCurrentLevel(int level);
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
 }
diff --git a/core/java/com/android/internal/app/IUsageStats.aidl b/core/java/com/android/internal/app/IUsageStats.aidl
index 6b053d5..1ea7409 100755
--- a/core/java/com/android/internal/app/IUsageStats.aidl
+++ b/core/java/com/android/internal/app/IUsageStats.aidl
@@ -22,6 +22,7 @@
 interface IUsageStats {
     void noteResumeComponent(in ComponentName componentName);
     void notePauseComponent(in ComponentName componentName);
+    void noteLaunchTime(in ComponentName componentName, int millis);
     PkgUsageStats getPkgUsageStats(in ComponentName componentName);
     PkgUsageStats[] getAllPkgUsageStats();
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8085080..77649f0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -21,9 +21,11 @@
 import android.os.Parcel;
 import android.os.ParcelFormatException;
 import android.os.Parcelable;
+import android.os.Process;
 import android.os.SystemClock;
 import android.telephony.TelephonyManager;
 import android.util.Log;
+import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.SparseArray;
 
@@ -31,9 +33,13 @@
 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.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
@@ -48,7 +54,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS' 
 
     // Current on-disk Parcel version
-    private static final int VERSION = 32;
+    private static final int VERSION = 34;
 
     private final File mFile;
     private final File mBackupFile;
@@ -63,11 +69,11 @@
     // elapsed time by the number of active timers to arrive at that timer's share of the time.
     // In order to do this, we must refresh each timer whenever the number of active timers
     // changes.
-    final ArrayList<Timer> mPartialTimers = new ArrayList<Timer>();
-    final ArrayList<Timer> mFullTimers = new ArrayList<Timer>();
-    final ArrayList<Timer> mWindowTimers = new ArrayList<Timer>();
-    final SparseArray<ArrayList<Timer>> mSensorTimers
-            = new SparseArray<ArrayList<Timer>>();
+    final ArrayList<StopwatchTimer> mPartialTimers = new ArrayList<StopwatchTimer>();
+    final ArrayList<StopwatchTimer> mFullTimers = new ArrayList<StopwatchTimer>();
+    final ArrayList<StopwatchTimer> mWindowTimers = new ArrayList<StopwatchTimer>();
+    final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
+            = new SparseArray<ArrayList<StopwatchTimer>>();
 
     // These are the objects that will want to do something when the device
     // is unplugged from power.
@@ -88,31 +94,33 @@
     long mLastRealtime;
     
     boolean mScreenOn;
-    Timer mScreenOnTimer;
+    StopwatchTimer mScreenOnTimer;
     
     int mScreenBrightnessBin = -1;
-    final Timer[] mScreenBrightnessTimer = new Timer[NUM_SCREEN_BRIGHTNESS_BINS];
+    final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
     
     Counter mInputEventCounter;
     
     boolean mPhoneOn;
-    Timer mPhoneOnTimer;
+    StopwatchTimer mPhoneOnTimer;
     
     int mPhoneSignalStrengthBin = -1;
-    final Timer[] mPhoneSignalStrengthsTimer = new Timer[NUM_SIGNAL_STRENGTH_BINS];
+    final StopwatchTimer[] mPhoneSignalStrengthsTimer = 
+            new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS];
     
     int mPhoneDataConnectionType = -1;
-    final Timer[] mPhoneDataConnectionsTimer = new Timer[NUM_DATA_CONNECTION_TYPES];
+    final StopwatchTimer[] mPhoneDataConnectionsTimer = 
+            new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
     
     boolean mWifiOn;
-    Timer mWifiOnTimer;
+    StopwatchTimer mWifiOnTimer;
     int mWifiOnUid = -1;
 
     boolean mWifiRunning;
-    Timer mWifiRunningTimer;
+    StopwatchTimer mWifiRunningTimer;
     
     boolean mBluetoothOn;
-    Timer mBluetoothOnTimer;
+    StopwatchTimer mBluetoothOnTimer;
     
     /**
      * These provide time bases that discount the time the device is plugged
@@ -131,10 +139,41 @@
     /*
      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
      */
-    int mUnpluggedStartLevel;
-    int mPluggedStartLevel;
+    int mDischargeStartLevel;
+    int mDischargeCurrentLevel;
     
     long mLastWriteTime = 0; // Milliseconds
+    
+    /*
+     * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
+     */
+    private final HashMap<String, SamplingTimer> mKernelWakelockStats = 
+            new HashMap<String, SamplingTimer>();
+    
+    public Map<String, ? extends SamplingTimer> getKernelWakelockStats() {
+        return mKernelWakelockStats;
+    }
+    
+    private static int sKernelWakelockUpdateVersion = 0;
+    
+    private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
+        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
+        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
+        Process.PROC_TAB_TERM,
+        Process.PROC_TAB_TERM,
+        Process.PROC_TAB_TERM,
+        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
+    };
+    
+    private final String[] mProcWakelocksName = new String[3];
+    private final long[] mProcWakelocksData = new long[3];
+    
+    /*
+     * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
+     * to mKernelWakelockStats.
+     */
+    private final Map<String, KernelWakelockStats> mProcWakelockFileStats = 
+            new HashMap<String, KernelWakelockStats>();
 
     // For debugging
     public BatteryStatsImpl() {
@@ -200,7 +239,7 @@
         }
 
         @Override
-        public int getCount(int which) {
+        public int getCountLocked(int which) {
             int val;
             if (which == STATS_LAST) {
                 val = mLastCount;
@@ -242,11 +281,9 @@
     /**
      * State for keeping track of timing information.
      */
-    public static final class Timer extends BatteryStats.Timer implements Unpluggable {
+    public static abstract class Timer extends BatteryStats.Timer implements Unpluggable {
         final int mType;
-        final ArrayList<Timer> mTimerPool;
-        
-        int mNesting;
+
         
         int mCount;
         int mLoadedCount;
@@ -281,24 +318,10 @@
          * power.
          */
         long mUnpluggedTime;
-
-        /**
-         * The last time at which we updated the timer.  If mNesting is > 0,
-         * subtract this from the current battery time to find the amount of
-         * time we have been running since we last computed an update.
-         */
-        long mUpdateTime;
         
-        /**
-         * The total time at which the timer was acquired, to determine if
-         * was actually held for an interesting duration.
-         */
-        long mAcquireTime;
-        
-        Timer(int type, ArrayList<Timer> timerPool,
-                ArrayList<Unpluggable> unpluggables, Parcel in) {
+        Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
             mType = type;
-            mTimerPool = timerPool;
+            
             mCount = in.readInt();
             mLoadedCount = in.readInt();
             mLastCount = in.readInt();
@@ -306,17 +329,19 @@
             mTotalTime = in.readLong();
             mLoadedTime = in.readLong();
             mLastTime = in.readLong();
-            mUpdateTime = in.readLong();
             mUnpluggedTime = in.readLong();
             unpluggables.add(this);
         }
 
-        Timer(int type, ArrayList<Timer> timerPool,
-                ArrayList<Unpluggable> unpluggables) {
+        Timer(int type, ArrayList<Unpluggable> unpluggables) {
             mType = type;
-            mTimerPool = timerPool;
             unpluggables.add(this);
         }
+
+        protected abstract long computeRunTimeLocked(long curBatteryRealtime);
+        
+        protected abstract int computeCurrentCountLocked();
+        
         
         public void writeToParcel(Parcel out, long batteryRealtime) {
             out.writeInt(mCount);
@@ -326,7 +351,6 @@
             out.writeLong(computeRunTimeLocked(batteryRealtime));
             out.writeLong(mLoadedTime);
             out.writeLong(mLastTime);
-            out.writeLong(mUpdateTime);
             out.writeLong(mUnpluggedTime);
         }
 
@@ -346,19 +370,15 @@
         }
 
         public void plug(long batteryUptime, long batteryRealtime) {
-            if (mNesting > 0) {
-                if (DEBUG && mType < 0) {
-                    Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
-                            + " old mTotalTime=" + mTotalTime
-                            + " old mUpdateTime=" + mUpdateTime);
-                }
-                mTotalTime = computeRunTimeLocked(batteryRealtime);
-                mUpdateTime = batteryRealtime;
-                if (DEBUG && mType < 0) {
-                    Log.v(TAG, "plug #" + mType
-                            + ": new mTotalTime=" + mTotalTime
-                            + " old mUpdateTime=" + mUpdateTime);
-                }
+            if (DEBUG && mType < 0) {
+                Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
+                        + " old mTotalTime=" + mTotalTime);
+            }
+            mTotalTime = computeRunTimeLocked(batteryRealtime);
+            mCount = computeCurrentCountLocked();
+            if (DEBUG && mType < 0) {
+                Log.v(TAG, "plug #" + mType
+                        + ": new mTotalTime=" + mTotalTime);
             }
         }
         
@@ -380,7 +400,7 @@
         }
 
         @Override
-        public long getTotalTime(long batteryRealtime, int which) {
+        public long getTotalTimeLocked(long batteryRealtime, int which) {
             long val;
             if (which == STATS_LAST) {
                 val = mLastTime;
@@ -397,12 +417,12 @@
         }
 
         @Override
-        public int getCount(int which) {
+        public int getCountLocked(int which) {
             int val;
             if (which == STATS_LAST) {
                 val = mLastCount;
             } else {
-                val = mCount;
+                val = computeCurrentCountLocked();
                 if (which == STATS_UNPLUGGED) {
                     val -= mUnpluggedCount;
                 } else if (which != STATS_TOTAL) {
@@ -414,14 +434,239 @@
         }
 
         public void logState(Printer pw, String prefix) {
-            pw.println(prefix + "mNesting=" + mNesting + " mCount=" + mCount
+            pw.println(prefix + " mCount=" + mCount
                     + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
                     + " mUnpluggedCount=" + mUnpluggedCount);
             pw.println(prefix + "mTotalTime=" + mTotalTime
                     + " mLoadedTime=" + mLoadedTime);
             pw.println(prefix + "mLastTime=" + mLastTime
                     + " mUnpluggedTime=" + mUnpluggedTime);
-            pw.println(prefix + "mUpdateTime=" + mUpdateTime
+        }
+        
+        
+        void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
+            long runTime = computeRunTimeLocked(batteryRealtime);
+            // Divide by 1000 for backwards compatibility
+            out.writeLong((runTime + 500) / 1000);
+            out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
+            out.writeInt(mCount);
+            out.writeInt(mCount - mLoadedCount);
+        }
+
+        void readSummaryFromParcelLocked(Parcel in) {
+            // Multiply by 1000 for backwards compatibility
+            mTotalTime = mLoadedTime = in.readLong() * 1000;
+            mLastTime = in.readLong() * 1000;
+            mUnpluggedTime = mTotalTime;
+            mCount = mLoadedCount = in.readInt();
+            mLastCount = in.readInt();
+            mUnpluggedCount = mCount;
+        }
+    }
+    
+    public static final class SamplingTimer extends Timer {
+        
+        /**
+         * The most recent reported count from /proc/wakelocks.
+         */
+        int mCurrentReportedCount;
+
+        /**
+         * The reported count from /proc/wakelocks when unplug() was last
+         * called.
+         */
+        int mUnpluggedReportedCount;
+
+        /**
+         * The most recent reported total_time from /proc/wakelocks.
+         */ 
+        long mCurrentReportedTotalTime;
+
+
+        /**
+         * The reported total_time from /proc/wakelocks when unplug() was last
+         * called.
+         */
+        long mUnpluggedReportedTotalTime;
+
+        /**
+         * Whether we are currently in a discharge cycle.
+         */
+        boolean mInDischarge;
+
+        /**
+         * Whether we are currently recording reported values.
+         */
+        boolean mTrackingReportedValues;
+        
+        /*
+         * A sequnce counter, incremented once for each update of the stats.
+         */
+        int mUpdateVersion;
+        
+        SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) {
+            super(0, unpluggables, in);
+            mCurrentReportedCount = in.readInt();
+            mUnpluggedReportedCount = in.readInt();
+            mCurrentReportedTotalTime = in.readLong();
+            mUnpluggedReportedTotalTime = in.readLong();
+            mTrackingReportedValues = in.readInt() == 1;
+            mInDischarge = inDischarge;
+        }
+        
+        SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, 
+                boolean trackReportedValues) {
+            super(0, unpluggables);
+            mTrackingReportedValues = trackReportedValues;
+            mInDischarge = inDischarge;
+        }
+        
+        public void setStale() {
+            mTrackingReportedValues = false;
+            mUnpluggedReportedTotalTime = 0;
+            mUnpluggedReportedCount = 0;
+        }
+        
+        public void setUpdateVersion(int version) {
+            mUpdateVersion = version;
+        }
+        
+        public int getUpdateVersion() {
+            return mUpdateVersion;
+        }
+        
+        public void updateCurrentReportedCount(int count) {
+            if (mInDischarge && mUnpluggedReportedCount == 0) {
+                // Updating the reported value for the first time.
+                mUnpluggedReportedCount = count;
+                // If we are receiving an update update mTrackingReportedValues;
+                mTrackingReportedValues = true;
+            }
+            mCurrentReportedCount = count;
+        }
+        
+        public void updateCurrentReportedTotalTime(long totalTime) {
+            if (mInDischarge && mUnpluggedReportedTotalTime == 0) {
+                // Updating the reported value for the first time.
+                mUnpluggedReportedTotalTime = totalTime;
+                // If we are receiving an update update mTrackingReportedValues;
+                mTrackingReportedValues = true;
+            }
+            mCurrentReportedTotalTime = totalTime;
+        }
+        
+        public void unplug(long batteryUptime, long batteryRealtime) {
+            super.unplug(batteryUptime, batteryRealtime);
+            if (mTrackingReportedValues) {
+                mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
+                mUnpluggedReportedCount = mCurrentReportedCount;
+            }
+            mInDischarge = true;
+        }
+
+        public void plug(long batteryUptime, long batteryRealtime) {
+            super.plug(batteryUptime, batteryRealtime);
+            mInDischarge = false;
+        }
+        
+        public void logState(Printer pw, String prefix) {
+            super.logState(pw, prefix);
+            pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount 
+                    + " mUnpluggedReportedCount=" + mUnpluggedReportedCount
+                    + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
+                    + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
+        }
+        
+        protected long computeRunTimeLocked(long curBatteryRealtime) {
+            return mTotalTime + (mInDischarge && mTrackingReportedValues 
+                    ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
+        }
+        
+        protected int computeCurrentCountLocked() {
+            return mCount + (mInDischarge && mTrackingReportedValues
+                    ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
+        }
+        
+        public void writeToParcel(Parcel out, long batteryRealtime) {
+            super.writeToParcel(out, batteryRealtime);
+            out.writeInt(mCurrentReportedCount);
+            out.writeInt(mUnpluggedReportedCount);
+            out.writeLong(mCurrentReportedTotalTime);
+            out.writeLong(mUnpluggedReportedTotalTime);
+            out.writeInt(mTrackingReportedValues ? 1 : 0);
+        }
+        
+        void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
+            super.writeSummaryFromParcelLocked(out, batteryRealtime);
+            out.writeLong(mCurrentReportedTotalTime);
+            out.writeInt(mCurrentReportedCount);
+            out.writeInt(mTrackingReportedValues ? 1 : 0);
+        }
+
+        void readSummaryFromParcelLocked(Parcel in) {
+            super.readSummaryFromParcelLocked(in);
+            mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong();
+            mUnpluggedReportedCount = mCurrentReportedCount = in.readInt();
+            mTrackingReportedValues = in.readInt() == 1;
+        }
+    }
+    
+    /**
+     * State for keeping track of timing information.
+     */
+    public static final class StopwatchTimer extends Timer {
+        final ArrayList<StopwatchTimer> mTimerPool;
+        int mNesting;
+
+
+        /**
+         * The last time at which we updated the timer.  If mNesting is > 0,
+         * subtract this from the current battery time to find the amount of
+         * time we have been running since we last computed an update.
+         */
+        long mUpdateTime;
+        
+        /**
+         * The total time at which the timer was acquired, to determine if
+         * was actually held for an interesting duration.
+         */
+        long mAcquireTime;
+        
+
+        StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+                ArrayList<Unpluggable> unpluggables, Parcel in) {
+            super(type, unpluggables, in);
+            mTimerPool = timerPool;
+            mUpdateTime = in.readLong();
+        }
+
+        StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
+                ArrayList<Unpluggable> unpluggables) {
+            super(type, unpluggables);
+            mTimerPool = timerPool;
+        }
+        
+        public void writeToParcel(Parcel out, long batteryRealtime) {
+            super.writeToParcel(out, batteryRealtime);
+            out.writeLong(mUpdateTime);
+        }
+
+        public void plug(long batteryUptime, long batteryRealtime) {
+            if (mNesting > 0) {
+                if (DEBUG && mType < 0) {
+                    Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
+                }
+                super.plug(batteryUptime, batteryRealtime);
+                mUpdateTime = batteryRealtime;
+                if (DEBUG && mType < 0) {
+                    Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
+                }
+            }
+        }
+
+        public void logState(Printer pw, String prefix) {
+            super.logState(pw, prefix);
+            pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime
                     + " mAcquireTime=" + mAcquireTime);
         }
         
@@ -484,12 +729,12 @@
         // Update the total time for all other running Timers with the same type as this Timer
         // due to a change in timer count
         private static void refreshTimersLocked(final BatteryStatsImpl stats,
-                final ArrayList<Timer> pool) {
+                final ArrayList<StopwatchTimer> pool) {
             final long realtime = SystemClock.elapsedRealtime() * 1000; 
             final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
             final int N = pool.size();
             for (int i=N-1; i>= 0; i--) {
-                final Timer t = pool.get(i);
+                final StopwatchTimer t = pool.get(i);
                 long heldTime = batteryRealtime - t.mUpdateTime;
                 if (heldTime > 0) {
                     t.mTotalTime += heldTime / N;
@@ -498,34 +743,146 @@
             }
         }
 
-        private long computeRunTimeLocked(long curBatteryRealtime) {
+        @Override
+        protected long computeRunTimeLocked(long curBatteryRealtime) {
             return mTotalTime + (mNesting > 0
                     ? (curBatteryRealtime - mUpdateTime)
                             / (mTimerPool != null ? mTimerPool.size() : 1)
                     : 0);
         }
 
-        void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
-            long runTime = computeRunTimeLocked(batteryRealtime);
-            // Divide by 1000 for backwards compatibility
-            out.writeLong((runTime + 500) / 1000);
-            out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
-            out.writeInt(mCount);
-            out.writeInt(mCount - mLoadedCount);
+        @Override
+        protected int computeCurrentCountLocked() {
+            return mCount;
         }
 
         void readSummaryFromParcelLocked(Parcel in) {
-            // Multiply by 1000 for backwards compatibility
-            mTotalTime = mLoadedTime = in.readLong() * 1000;
-            mLastTime = in.readLong() * 1000;
-            mUnpluggedTime = mTotalTime;
-            mCount = mLoadedCount = in.readInt();
-            mLastCount = in.readInt();
-            mUnpluggedCount = mCount;
+            super.readSummaryFromParcelLocked(in);
             mNesting = 0;
         }
     }
     
+    private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
+        
+        byte[] buffer = new byte[4096];
+        int len;
+        
+        try {
+            FileInputStream is = new FileInputStream("/proc/wakelocks");
+            len = is.read(buffer);
+            is.close();
+
+            if (len > 0) {
+                int i;
+                for (i=0; i<len; i++) {
+                    if (buffer[i] == '\0') {
+                        len = i;
+                        break;
+                    }
+                }
+            }
+        } catch (java.io.FileNotFoundException e) {
+            return null;
+        } catch (java.io.IOException e) {
+            return null;
+        }
+        
+        return parseProcWakelocks(buffer, len);
+    }
+    
+    private final Map<String, KernelWakelockStats> parseProcWakelocks(
+            byte[] wlBuffer, int len) {
+        String name;
+        int count;
+        long totalTime;
+        int startIndex, endIndex;
+        int numUpdatedWlNames = 0;
+
+        // Advance past the first line.
+        int i;
+        for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
+        startIndex = endIndex = i + 1;
+
+        synchronized(this) {
+            Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
+            
+            sKernelWakelockUpdateVersion++;
+            while (endIndex < len) {
+                for (endIndex=startIndex; 
+                        endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0'; 
+                        endIndex++);
+                endIndex++; // endIndex is an exclusive upper bound.
+
+                String[] nameStringArray = mProcWakelocksName;
+                long[] wlData = mProcWakelocksData;
+                Process.parseProcLine(wlBuffer, startIndex, endIndex, PROC_WAKELOCKS_FORMAT, 
+                        nameStringArray, wlData, null);
+                
+                name = nameStringArray[0];
+                count = (int) wlData[1];
+                // convert nanoseconds to microseconds with rounding.
+                totalTime = (wlData[2] + 500) / 1000;
+
+                if (name.length() > 0) {
+                    if (!m.containsKey(name)) {
+                        m.put(name, new KernelWakelockStats(count, totalTime, 
+                                sKernelWakelockUpdateVersion));
+                        numUpdatedWlNames++;
+                    } else {
+                        KernelWakelockStats kwlStats = m.get(name);
+                        if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
+                            kwlStats.mCount += count;
+                            kwlStats.mTotalTime += totalTime;
+                        } else {
+                            kwlStats.mCount = count;
+                            kwlStats.mTotalTime = totalTime;
+                            kwlStats.mVersion = sKernelWakelockUpdateVersion;
+                            numUpdatedWlNames++;
+                        }
+                    }
+                }              
+                startIndex = endIndex;
+            }
+
+            if (m.size() != numUpdatedWlNames) {
+                // Don't report old data.
+                Iterator<KernelWakelockStats> itr = m.values().iterator();
+                while (itr.hasNext()) {
+                    if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
+                        itr.remove();
+                    }
+                }
+            }
+            return m;
+        }
+    }
+    
+    private class KernelWakelockStats {
+        public int mCount;
+        public long mTotalTime;
+        public int mVersion;
+        
+        KernelWakelockStats(int count, long totalTime, int version) {
+            mCount = count;
+            mTotalTime = totalTime;
+            mVersion = version;
+        }
+    }
+    
+    /*
+     * Get the KernelWakelockTimer associated with name, and create a new one if one 
+     * doesn't already exist.
+     */
+    public SamplingTimer getKernelWakelockTimerLocked(String name) {
+        SamplingTimer kwlt = mKernelWakelockStats.get(name);
+        if (kwlt == null) {
+            kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 
+                    true /* track reported values */);
+            mKernelWakelockStats.put(name, kwlt);
+        }
+        return kwlt;
+    }
+    
     public void doUnplug(long batteryUptime, long batteryRealtime) {
         for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
             Uid u = mUidStats.valueAt(iu);
@@ -760,53 +1117,53 @@
     }
     
     @Override public long getScreenOnTime(long batteryRealtime, int which) {
-        return mScreenOnTimer.getTotalTime(batteryRealtime, which);
+        return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
     }
     
     @Override public long getScreenBrightnessTime(int brightnessBin,
             long batteryRealtime, int which) {
-        return mScreenBrightnessTimer[brightnessBin].getTotalTime(
+        return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
                 batteryRealtime, which);
     }
     
     @Override public int getInputEventCount(int which) {
-        return mInputEventCounter.getCount(which);
+        return mInputEventCounter.getCountLocked(which);
     }
     
     @Override public long getPhoneOnTime(long batteryRealtime, int which) {
-        return mPhoneOnTimer.getTotalTime(batteryRealtime, which);
+        return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
     }
     
     @Override public long getPhoneSignalStrengthTime(int strengthBin,
             long batteryRealtime, int which) {
-        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTime(
+        return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
                 batteryRealtime, which);
     }
     
     @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
-        return mPhoneDataConnectionsTimer[dataType].getCount(which);
+        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
     }
     
     @Override public long getPhoneDataConnectionTime(int dataType,
             long batteryRealtime, int which) {
-        return mPhoneDataConnectionsTimer[dataType].getTotalTime(
+        return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
                 batteryRealtime, which);
     }
     
     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
-        return mPhoneDataConnectionsTimer[dataType].getCount(which);
+        return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
     }
     
     @Override public long getWifiOnTime(long batteryRealtime, int which) {
-        return mWifiOnTimer.getTotalTime(batteryRealtime, which);
+        return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
     }
     
     @Override public long getWifiRunningTime(long batteryRealtime, int which) {
-        return mWifiRunningTimer.getTotalTime(batteryRealtime, which);
+        return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
     }
 
     @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
-        return mBluetoothOnTimer.getTotalTime(batteryRealtime, which);
+        return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
     }
     
     @Override public boolean getIsOnBattery() {
@@ -836,13 +1193,13 @@
         long mStartedTcpBytesSent = -1;
         
         boolean mWifiTurnedOn;
-        Timer mWifiTurnedOnTimer;
+        StopwatchTimer mWifiTurnedOnTimer;
         
         boolean mFullWifiLockOut;
-        Timer mFullWifiLockTimer;
+        StopwatchTimer mFullWifiLockTimer;
         
         boolean mScanWifiLockOut;
-        Timer mScanWifiLockTimer;
+        StopwatchTimer mScanWifiLockTimer;
         
         Counter[] mUserActivityCounters;
         
@@ -868,9 +1225,9 @@
         
         public Uid(int uid) {
             mUid = uid;
-            mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables);
-            mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables);
-            mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables);
+            mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables);
+            mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables);
+            mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
         }
 
         @Override
@@ -980,17 +1337,17 @@
         
         @Override 
         public long getWifiTurnedOnTime(long batteryRealtime, int which) {
-            return mWifiTurnedOnTimer.getTotalTime(batteryRealtime, which);
+            return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
         }
         
         @Override 
         public long getFullWifiLockTime(long batteryRealtime, int which) {
-            return mFullWifiLockTimer.getTotalTime(batteryRealtime, which);
+            return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
         }
         
         @Override 
         public long getScanWifiLockTime(long batteryRealtime, int which) {
-            return mScanWifiLockTimer.getTotalTime(batteryRealtime, which);
+            return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
         }
         
         @Override
@@ -1013,7 +1370,7 @@
             if (mUserActivityCounters == null) {
                 return 0;
             }
-            return mUserActivityCounters[type].getCount(which);
+            return mUserActivityCounters[type].getCountLocked(which);
         }
         
         void initUserActivityLocked() {
@@ -1120,11 +1477,11 @@
             mTcpBytesReceivedAtLastUnplug = in.readLong();
             mTcpBytesSentAtLastUnplug = in.readLong();
             mWifiTurnedOn = false;
-            mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables, in);
+            mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in);
             mFullWifiLockOut = false;
-            mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in);
+            mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in);
             mScanWifiLockOut = false;
-            mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
+            mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
             if (in.readInt() == 0) {
                 mUserActivityCounters = null;
             } else {
@@ -1142,17 +1499,17 @@
             /**
              * How long (in ms) this uid has been keeping the device partially awake.
              */
-            Timer mTimerPartial;
+            StopwatchTimer mTimerPartial;
 
             /**
              * How long (in ms) this uid has been keeping the device fully awake.
              */
-            Timer mTimerFull;
+            StopwatchTimer mTimerFull;
 
             /**
              * How long (in ms) this uid has had a window keeping the device awake.
              */
-            Timer mTimerWindow;
+            StopwatchTimer mTimerWindow;
 
             /**
              * Reads a possibly null Timer from a Parcel.  The timer is associated with the
@@ -1161,13 +1518,13 @@
              * @param in the Parcel to be read from.
              * return a new Timer, or null.
              */
-            private Timer readTimerFromParcel(int type, ArrayList<Timer> pool,
+            private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
                     ArrayList<Unpluggable> unpluggables, Parcel in) {
                 if (in.readInt() == 0) {
                     return null;
                 }
 
-                return new Timer(type, pool, unpluggables, in);
+                return new StopwatchTimer(type, pool, unpluggables, in);
             }
 
             void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -1198,24 +1555,24 @@
 
         public final class Sensor extends BatteryStats.Uid.Sensor {
             final int mHandle;
-            Timer mTimer;
+            StopwatchTimer mTimer;
             
             public Sensor(int handle) {
                 mHandle = handle;
             }
 
-            private Timer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
+            private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
                     Parcel in) {
                 if (in.readInt() == 0) {
                     return null;
                 }
 
-                ArrayList<Timer> pool = mSensorTimers.get(mHandle);
+                ArrayList<StopwatchTimer> pool = mSensorTimers.get(mHandle);
                 if (pool == null) {
-                    pool = new ArrayList<Timer>();
+                    pool = new ArrayList<StopwatchTimer>();
                     mSensorTimers.put(mHandle, pool);
                 }
-                return new Timer(0, pool, unpluggables, in);
+                return new StopwatchTimer(0, pool, unpluggables, in);
             }
 
             void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -1816,32 +2173,32 @@
             return ss;
         }
 
-        public Timer getWakeTimerLocked(String name, int type) {
+        public StopwatchTimer getWakeTimerLocked(String name, int type) {
             Wakelock wl = mWakelockStats.get(name);
             if (wl == null) {
                 wl = new Wakelock();
                 mWakelockStats.put(name, wl);
             }
-            Timer t = null;
+            StopwatchTimer t = null;
             switch (type) {
                 case WAKE_TYPE_PARTIAL:
                     t = wl.mTimerPartial;
                     if (t == null) {
-                        t = new Timer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
+                        t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
                         wl.mTimerPartial = t;
                     }
                     return t;
                 case WAKE_TYPE_FULL:
                     t = wl.mTimerFull;
                     if (t == null) {
-                        t = new Timer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
+                        t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
                         wl.mTimerFull = t;
                     }
                     return t;
                 case WAKE_TYPE_WINDOW:
                     t = wl.mTimerWindow;
                     if (t == null) {
-                        t = new Timer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
+                        t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
                         wl.mTimerWindow = t;
                     }
                     return t;
@@ -1850,7 +2207,7 @@
             }
         }
 
-        public Timer getSensorTimerLocked(int sensor, boolean create) {
+        public StopwatchTimer getSensorTimerLocked(int sensor, boolean create) {
             Sensor se = mSensorStats.get(sensor);
             if (se == null) {
                 if (!create) {
@@ -1859,36 +2216,36 @@
                 se = new Sensor(sensor);
                 mSensorStats.put(sensor, se);
             }
-            Timer t = se.mTimer;
+            StopwatchTimer t = se.mTimer;
             if (t != null) {
                 return t;
             }
-            ArrayList<Timer> timers = mSensorTimers.get(sensor);
+            ArrayList<StopwatchTimer> timers = mSensorTimers.get(sensor);
             if (timers == null) {
-                timers = new ArrayList<Timer>();
+                timers = new ArrayList<StopwatchTimer>();
                 mSensorTimers.put(sensor, timers);
             }
-            t = new Timer(BatteryStats.SENSOR, timers, mUnpluggables);
+            t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables);
             se.mTimer = t;
             return t;
         }
 
         public void noteStartWakeLocked(String name, int type) {
-            Timer t = getWakeTimerLocked(name, type);
+            StopwatchTimer t = getWakeTimerLocked(name, type);
             if (t != null) {
                 t.startRunningLocked(BatteryStatsImpl.this);
             }
         }
 
         public void noteStopWakeLocked(String name, int type) {
-            Timer t = getWakeTimerLocked(name, type);
+            StopwatchTimer t = getWakeTimerLocked(name, type);
             if (t != null) {
                 t.stopRunningLocked(BatteryStatsImpl.this);
             }
         }
         
         public void noteStartSensor(int sensor) {
-            Timer t = getSensorTimerLocked(sensor, true);
+            StopwatchTimer t = getSensorTimerLocked(sensor, true);
             if (t != null) {
                 t.startRunningLocked(BatteryStatsImpl.this);
             }            
@@ -1896,21 +2253,21 @@
 
         public void noteStopSensor(int sensor) {
             // Don't create a timer if one doesn't already exist
-            Timer t = getSensorTimerLocked(sensor, false);
+            StopwatchTimer t = getSensorTimerLocked(sensor, false);
             if (t != null) {
                 t.stopRunningLocked(BatteryStatsImpl.this);
             }            
         }
         
         public void noteStartGps() {
-            Timer t = getSensorTimerLocked(Sensor.GPS, true);
+            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
             if (t != null) {
                 t.startRunningLocked(BatteryStatsImpl.this);
             }  
         }
         
         public void noteStopGps() {
-            Timer t = getSensorTimerLocked(Sensor.GPS, false);
+            StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
             if (t != null) {
                 t.stopRunningLocked(BatteryStatsImpl.this);
             }  
@@ -1925,21 +2282,21 @@
         mFile = new File(filename);
         mBackupFile = new File(filename + ".bak");
         mStartCount++;
-        mScreenOnTimer = new Timer(-1, null, mUnpluggables);
+        mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i] = new Timer(-100-i, null, mUnpluggables);
+            mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables);
         }
         mInputEventCounter = new Counter(mUnpluggables);
-        mPhoneOnTimer = new Timer(-2, null, mUnpluggables);
+        mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables);
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i] = new Timer(-200-i, null, mUnpluggables);
+            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
         }
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i] = new Timer(-300-i, null, mUnpluggables);
+            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
         }
-        mWifiOnTimer = new Timer(-3, null, mUnpluggables);
-        mWifiRunningTimer = new Timer(-4, null, mUnpluggables);
-        mBluetoothOnTimer = new Timer(-5, null, mUnpluggables);
+        mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables);
+        mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables);
+        mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables);
         mOnBattery = mOnBatteryInternal = false;
         mTrackBatteryPastUptime = 0;
         mTrackBatteryPastRealtime = 0;
@@ -1947,8 +2304,8 @@
         mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
         mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
         mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
-        mUnpluggedStartLevel = 0;
-        mPluggedStartLevel = 0;
+        mDischargeStartLevel = 0;
+        mDischargeCurrentLevel = 0;
     }
 
     public BatteryStatsImpl(Parcel p) {
@@ -1967,6 +2324,7 @@
 
     public void setOnBattery(boolean onBattery, int level) {
         synchronized(this) {
+            updateKernelWakelocksLocked();
             if (mOnBattery != onBattery) {
                 mOnBattery = mOnBatteryInternal = onBattery;
                 
@@ -1978,12 +2336,12 @@
                     mTrackBatteryRealtimeStart = realtime;
                     mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
                     mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
-                    mUnpluggedStartLevel = level;
+                    mDischargeCurrentLevel = mDischargeStartLevel = level;
                     doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
                 } else {
                     mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
                     mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
-                    mPluggedStartLevel = level;
+                    mDischargeCurrentLevel = level;
                     doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
                 }
                 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
@@ -1994,6 +2352,39 @@
             }
         }
     }
+    
+    public void recordCurrentLevel(int level) {
+        mDischargeCurrentLevel = level;
+    }
+    
+    public void updateKernelWakelocksLocked() {
+        Map<String, KernelWakelockStats> m = readKernelWakelockStats();
+        
+        for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
+            String name = ent.getKey();
+            KernelWakelockStats kws = ent.getValue();
+        
+            SamplingTimer kwlt = mKernelWakelockStats.get(name);
+            if (kwlt == null) {
+                kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, 
+                        true /* track reported values */);
+                mKernelWakelockStats.put(name, kwlt);
+            }
+            kwlt.updateCurrentReportedCount(kws.mCount);
+            kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
+            kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
+        }
+        
+        if (m.size() != mKernelWakelockStats.size()) {
+            // Set timers to stale if they didn't appear in /proc/wakelocks this time.
+            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+                SamplingTimer st = ent.getValue();
+                if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
+                    st.setStale();
+                }
+            }
+        }
+    }
 
     public long getAwakeTimeBattery() {
         return computeBatteryUptime(getBatteryUptimeLocked(), STATS_CURRENT);
@@ -2086,25 +2477,25 @@
     }
     
     @Override
-    public int getUnpluggedStartLevel() {
+    public int getDischargeStartLevel() {
         synchronized(this) {
-            return getUnluggedStartLevelLocked();
+            return getDischargeStartLevelLocked();
         }
     }
     
-    public int getUnluggedStartLevelLocked() {
-            return mUnpluggedStartLevel;
+    public int getDischargeStartLevelLocked() {
+            return mDischargeStartLevel;
     }
     
     @Override
-    public int getPluggedStartLevel() {
+    public int getDischargeCurrentLevel() {
         synchronized(this) {
-            return getPluggedStartLevelLocked();
+            return getDischargeCurrentLevelLocked();
         }
     }
     
-    public int getPluggedStartLevelLocked() {
-            return mPluggedStartLevel;
+    public int getDischargeCurrentLevelLocked() {
+            return mDischargeCurrentLevel;
     }
 
     /**
@@ -2266,8 +2657,8 @@
         mLastUptime = in.readLong();
         mRealtime = in.readLong();
         mLastRealtime = in.readLong();
-        mUnpluggedStartLevel = in.readInt();
-        mPluggedStartLevel = in.readInt();
+        mDischargeStartLevel = in.readInt();
+        mDischargeCurrentLevel = in.readInt();
         
         mStartCount++;
         
@@ -2292,6 +2683,14 @@
         mBluetoothOn = false;
         mBluetoothOnTimer.readSummaryFromParcelLocked(in);
 
+        int NKW = in.readInt();
+        for (int ikw = 0; ikw < NKW; ikw++) {
+            if (in.readInt() != 0) {
+                String kwltName = in.readString();
+                getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
+            }
+        }
+        
         final int NU = in.readInt();
         for (int iu = 0; iu < NU; iu++) {
             int uid = in.readInt();
@@ -2396,8 +2795,8 @@
         out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT));
-        out.writeInt(mUnpluggedStartLevel);
-        out.writeInt(mPluggedStartLevel);
+        out.writeInt(mDischargeStartLevel);
+        out.writeInt(mDischargeCurrentLevel);
         
         
         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
@@ -2416,6 +2815,18 @@
         mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
         mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
 
+        out.writeInt(mKernelWakelockStats.size());
+        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+            Timer kwlt = ent.getValue();
+            if (kwlt != null) {
+                out.writeInt(1);
+                out.writeString(ent.getKey());
+                ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL);
+            } else {
+                out.writeInt(0);
+            }
+        }
+        
         final int NU = mUidStats.size();
         out.writeInt(NU);
         for (int iu = 0; iu < NU; iu++) {
@@ -2544,25 +2955,25 @@
         mBatteryRealtime = in.readLong();
         mBatteryLastRealtime = in.readLong();
         mScreenOn = false;
-        mScreenOnTimer = new Timer(-1, null, mUnpluggables, in);
+        mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i] = new Timer(-100-i, null, mUnpluggables, in);
+            mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in);
         }
         mInputEventCounter = new Counter(mUnpluggables, in);
         mPhoneOn = false;
-        mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in);
+        mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
         for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i] = new Timer(-200-i, null, mUnpluggables, in);
+            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
         }
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i] = new Timer(-300-i, null, mUnpluggables, in);
+            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
         }
         mWifiOn = false;
-        mWifiOnTimer = new Timer(-2, null, mUnpluggables, in);
+        mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
         mWifiRunning = false;
-        mWifiRunningTimer = new Timer(-2, null, mUnpluggables, in);
+        mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
         mBluetoothOn = false;
-        mBluetoothOnTimer = new Timer(-2, null, mUnpluggables, in);
+        mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
         mUptime = in.readLong();
         mUptimeStart = in.readLong();
         mLastUptime = in.readLong();
@@ -2577,10 +2988,20 @@
         mTrackBatteryRealtimeStart = in.readLong();
         mUnpluggedBatteryUptime = in.readLong();
         mUnpluggedBatteryRealtime = in.readLong();
-        mUnpluggedStartLevel = in.readInt();
-        mPluggedStartLevel = in.readInt();
+        mDischargeStartLevel = in.readInt();
+        mDischargeCurrentLevel = in.readInt();
         mLastWriteTime = in.readLong();
 
+        mKernelWakelockStats.clear();
+        int NKW = in.readInt();
+        for (int ikw = 0; ikw < NKW; ikw++) {
+            if (in.readInt() != 0) {
+                String wakelockName = in.readString();
+                SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in);
+                mKernelWakelockStats.put(wakelockName, kwlt);
+            }
+        }
+        
         mPartialTimers.clear();
         mFullTimers.clear();
         mWindowTimers.clear();
@@ -2640,10 +3061,22 @@
         out.writeLong(mTrackBatteryRealtimeStart);
         out.writeLong(mUnpluggedBatteryUptime);
         out.writeLong(mUnpluggedBatteryRealtime);
-        out.writeInt(mUnpluggedStartLevel);
-        out.writeInt(mPluggedStartLevel);
+        out.writeInt(mDischargeStartLevel);
+        out.writeInt(mDischargeCurrentLevel);
         out.writeLong(mLastWriteTime);
 
+        out.writeInt(mKernelWakelockStats.size());
+        for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+            SamplingTimer kwlt = ent.getValue();
+            if (kwlt != null) {
+                out.writeInt(1);
+                out.writeString(ent.getKey());
+                Timer.writeTimerToParcel(out, kwlt, batteryRealtime);
+            } else {
+                out.writeInt(0);
+            }
+        }
+        
         int size = mUidStats.size();
         out.writeInt(size);
         for (int i = 0; i < size; i++) {
@@ -2665,32 +3098,33 @@
         }
     };
     
-    public void dumpLocked(Printer pw) {
+    public void dumpLocked(PrintWriter pw) {
         if (DEBUG) {
-            pw.println("*** Screen timer:");
-            mScreenOnTimer.logState(pw, "  ");
+            Printer pr = new PrintWriterPrinter(pw);
+            pr.println("*** Screen timer:");
+            mScreenOnTimer.logState(pr, "  ");
             for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-                pw.println("*** Screen brightness #" + i + ":");
-                mScreenBrightnessTimer[i].logState(pw, "  ");
+                pr.println("*** Screen brightness #" + i + ":");
+                mScreenBrightnessTimer[i].logState(pr, "  ");
             }
-            pw.println("*** Input event counter:");
-            mInputEventCounter.logState(pw, "  ");
-            pw.println("*** Phone timer:");
-            mPhoneOnTimer.logState(pw, "  ");
+            pr.println("*** Input event counter:");
+            mInputEventCounter.logState(pr, "  ");
+            pr.println("*** Phone timer:");
+            mPhoneOnTimer.logState(pr, "  ");
             for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
-                pw.println("*** Signal strength #" + i + ":");
-                mPhoneSignalStrengthsTimer[i].logState(pw, "  ");
+                pr.println("*** Signal strength #" + i + ":");
+                mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
             }
             for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-                pw.println("*** Data connection type #" + i + ":");
-                mPhoneDataConnectionsTimer[i].logState(pw, "  ");
+                pr.println("*** Data connection type #" + i + ":");
+                mPhoneDataConnectionsTimer[i].logState(pr, "  ");
             }
-            pw.println("*** Wifi timer:");
-            mWifiOnTimer.logState(pw, "  ");
-            pw.println("*** WifiRunning timer:");
-            mWifiRunningTimer.logState(pw, "  ");
-            pw.println("*** Bluetooth timer:");
-            mBluetoothOnTimer.logState(pw, "  ");
+            pr.println("*** Wifi timer:");
+            mWifiOnTimer.logState(pr, "  ");
+            pr.println("*** WifiRunning timer:");
+            mWifiRunningTimer.logState(pr, "  ");
+            pr.println("*** Bluetooth timer:");
+            mBluetoothOnTimer.logState(pr, "  ");
         }
         super.dumpLocked(pw);
     }
diff --git a/core/java/com/android/internal/util/BitwiseInputStream.java b/core/java/com/android/internal/util/BitwiseInputStream.java
new file mode 100644
index 0000000..4757919
--- /dev/null
+++ b/core/java/com/android/internal/util/BitwiseInputStream.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+/**
+ * An object that provides bitwise incremental read access to a byte array.
+ *
+ * This is useful, for example, when accessing a series of fields that
+ * may not be aligned on byte boundaries.
+ *
+ * NOTE -- This class is not threadsafe.
+ */
+public class BitwiseInputStream {
+
+    // The byte array being read from.
+    private byte[] mBuf;
+
+    // The current position offset, in bits, from the msb in byte 0.
+    private int mPos;
+
+    // The last valid bit offset.
+    private int mEnd;
+
+    /**
+     * An exception to report access problems.
+     */
+    public static class AccessException extends Exception {
+        public AccessException(String s) {
+            super("BitwiseInputStream access failed: " + s);
+        }
+    }
+
+    /**
+     * Create object from byte array.
+     *
+     * @param buf a byte array containing data
+     */
+    public BitwiseInputStream(byte buf[]) {
+        mBuf = buf;
+        mEnd = buf.length << 3;
+        mPos = 0;
+    }
+
+    /**
+     * Return the number of bit still available for reading.
+     */
+    public int available() {
+        return mEnd - mPos;
+    }
+
+    /**
+     * Read some data and increment the current position.
+     *
+     * @param bits the amount of data to read (gte 0, lte 8)
+     *
+     * @return byte of read data (possibly partially filled, from lsb)
+     */
+    public byte read(int bits) throws AccessException {
+        int index = mPos >>> 3;
+        int offset = 16 - (mPos & 0x07) - bits;  // &7==%8
+        if ((bits < 0) || (bits > 8) || ((mPos + bits) > mEnd)) {
+            throw new AccessException("illegal read " +
+                "(pos " + mPos + ", end " + mEnd + ", bits " + bits + ")");
+        }
+        int data = (mBuf[index] & 0x00FF) << 8;
+        if (offset < 8) data |= (mBuf[index + 1] & 0xFF);
+        data >>>= offset;
+        data &= (-1 >>> (32 - bits));
+        mPos += bits;
+        return (byte)data;
+    }
+
+    /**
+     * Read data in bulk into a byte array and increment the current position.
+     *
+     * @param bits the amount of data to read
+     *
+     * @return newly allocated byte array of read data
+     */
+    public byte[] readByteArray(int bits) throws AccessException {
+        int bytes = (bits >>> 3) + ((bits & 0x07) > 0 ? 1 : 0);  // &7==%8
+        byte[] arr = new byte[bytes];
+        for (int i = 0; i < bytes; i++) {
+            int increment = Math.min(8, bits - (i << 3));
+            arr[i] = (byte)(read(increment) << (8 - increment));
+        }
+        return arr;
+    }
+
+    /**
+     * Increment the current position and ignore contained data.
+     *
+     * @param bits the amount by which to increment the position
+     */
+    public void skip(int bits) throws AccessException {
+        if ((mPos + bits) > mEnd) {
+            throw new AccessException("illegal skip " +
+                "(pos " + mPos + ", end " + mEnd + ", bits " + bits + ")");
+        }
+        mPos += bits;
+    }
+}
diff --git a/core/java/com/android/internal/util/BitwiseOutputStream.java b/core/java/com/android/internal/util/BitwiseOutputStream.java
new file mode 100644
index 0000000..17f5c7c
--- /dev/null
+++ b/core/java/com/android/internal/util/BitwiseOutputStream.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+/**
+ * An object that rovides bitwise incremental write access to a byte array.
+ *
+ * This is useful, for example, when writing a series of fields that
+ * may not be aligned on byte boundaries.
+ *
+ * NOTE -- This class is not threadsafe.
+ */
+public class BitwiseOutputStream {
+
+    // The byte array being written to, which will be grown as needed.
+    private byte[] mBuf;
+
+    // The current position offset, in bits, from the msb in byte 0.
+    private int mPos;
+
+    // The last bit offset, given the current buf length.
+    private int mEnd;
+
+    /**
+     * An exception to report access problems.
+     */
+    public static class AccessException extends Exception {
+        public AccessException(String s) {
+            super("BitwiseOutputStream access failed: " + s);
+        }
+    }
+
+    /**
+     * Create object from hint at desired size.
+     *
+     * @param startingLength initial internal byte array length in bytes
+     */
+    public BitwiseOutputStream(int startingLength) {
+        mBuf = new byte[startingLength];
+        mEnd = startingLength << 3;
+        mPos = 0;
+    }
+
+    /**
+     * Return byte array containing accumulated data, sized to just fit.
+     *
+     * @return newly allocated byte array
+     */
+    public byte[] toByteArray() {
+        int len = (mPos >>> 3) + ((mPos & 0x07) > 0 ? 1 : 0);  // &7==%8
+        byte[] newBuf = new byte[len];
+        System.arraycopy(mBuf, 0, newBuf, 0, len);
+        return newBuf;
+    }
+
+    /**
+     * Allocate a new internal buffer, if needed.
+     *
+     * @param bits additional bits to be accommodated
+     */
+    private void possExpand(int bits) {
+        if ((mPos + bits) < mEnd) return;
+        byte[] newBuf = new byte[(mPos + bits) >>> 2];
+        System.arraycopy(mBuf, 0, newBuf, 0, mEnd >>> 3);
+        mBuf = newBuf;
+    }
+
+    /**
+     * Write some data and increment the current position.
+     *
+     * @param bits the amount of data to write (gte 0, lte 8)
+     * @param data to write, will be masked to expose only bits param from lsb
+     */
+    public void write(int bits, int data) throws AccessException {
+        if ((bits < 0) || (bits > 8)) {
+            throw new AccessException("illegal write (" + bits + " bits)");
+        }
+        possExpand(bits);
+        data &= (-1 >>> (32 - bits));
+        int index = mPos >>> 3;
+        int offset = 16 - (mPos & 0x07) - bits;  // &7==%8
+        data <<= offset;
+        mPos += bits;
+        mBuf[index] |= (data >>> 8);
+        if (offset < 8) mBuf[index + 1] |= (data & 0x00FF);
+    }
+
+    /**
+     * Write data in bulk from a byte array and increment the current position.
+     *
+     * @param bits the amount of data to write
+     * @param arr the byte array containing data to be written
+     */
+    public void writeByteArray(int bits, byte[] arr) throws AccessException {
+        for (int i = 0; i < arr.length; i++) {
+            int increment = Math.min(8, bits - (i << 3));
+            if (increment > 0) {
+                write(increment, (byte)(arr[i] >>> (8 - increment)));
+            }
+        }
+    }
+
+    /**
+     * Increment the current position, implicitly writing zeros.
+     *
+     * @param bits the amount by which to increment the position
+     */
+    public void skip(int bits) {
+        possExpand(bits);
+        mPos += bits;
+    }
+}
diff --git a/core/java/com/android/internal/util/TypedProperties.java b/core/java/com/android/internal/util/TypedProperties.java
new file mode 100644
index 0000000..48479e3
--- /dev/null
+++ b/core/java/com/android/internal/util/TypedProperties.java
@@ -0,0 +1,692 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StreamTokenizer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * A {@code Map} that publishes a set of typed properties, defined by
+ * zero or more {@code Reader}s containing textual definitions and assignments.
+ */
+public class TypedProperties extends HashMap<String, Object> {
+    /**
+     * Instantiates a {@link java.io.StreamTokenizer} and sets its syntax tables
+     * appropriately for the {@code TypedProperties} file format.
+     *
+     * @param r The {@code Reader} that the {@code StreamTokenizer} will read from
+     * @return a newly-created and initialized {@code StreamTokenizer}
+     */
+    static StreamTokenizer initTokenizer(Reader r) {
+        StreamTokenizer st = new StreamTokenizer(r);
+
+        // Treat everything we don't specify as "ordinary".
+        st.resetSyntax();
+
+        /* The only non-quoted-string words we'll be reading are:
+         * - property names: [._$a-zA-Z0-9]
+         * - type names (case insensitive): [a-zA-Z]
+         * - number literals: [-0-9.eExXA-Za-z]  ('x' for 0xNNN hex literals. "NaN", "Infinity")
+         * - "true" or "false" (case insensitive): [a-zA-Z]
+         */
+        st.wordChars('0', '9');
+        st.wordChars('A', 'Z');
+        st.wordChars('a', 'z');
+        st.wordChars('_', '_');
+        st.wordChars('$', '$');
+        st.wordChars('.', '.');
+        st.wordChars('-', '-');
+        st.wordChars('+', '+');
+
+        // Single-character tokens
+        st.ordinaryChar('=');
+
+        // Other special characters
+        st.whitespaceChars(' ', ' ');
+        st.whitespaceChars('\t', '\t');
+
+        st.quoteChar('"');
+
+        st.commentChar('#');
+
+        st.eolIsSignificant(true);
+
+        return st;
+    }
+
+
+    /**
+     * An unchecked exception that is thrown when encountering a syntax
+     * or semantic error in the input.
+     */
+    public static class ParseException extends IllegalArgumentException {
+        ParseException(StreamTokenizer state, String expected) {
+            super("expected " + expected + ", saw " + state.toString());
+        }
+    }
+
+    // A sentinel instance used to indicate a null string.
+    static final String NULL_STRING = new String("<TypedProperties:NULL_STRING>");
+
+    // Constants used to represent the supported types.
+    static final int TYPE_UNSET = 'x';
+    static final int TYPE_BOOLEAN = 'Z';
+    static final int TYPE_BYTE = 'I' | 1 << 8;
+    // TYPE_CHAR: character literal syntax not supported; use short.
+    static final int TYPE_SHORT = 'I' | 2 << 8;
+    static final int TYPE_INT = 'I' | 4 << 8;
+    static final int TYPE_LONG = 'I' | 8 << 8;
+    static final int TYPE_FLOAT = 'F' | 4 << 8;
+    static final int TYPE_DOUBLE = 'F' | 8 << 8;
+    static final int TYPE_STRING = 'L' | 's' << 8;
+    static final int TYPE_ERROR = -1;
+
+    /**
+     * Converts a case-insensitive string to an internal type constant.
+     *
+     * @param typeName the type name to convert
+     * @return the type constant that corresponds to {@code typeName},
+     *         or {@code TYPE_ERROR} if the type is unknown
+     */
+    static int interpretType(String typeName) {
+        if ("unset".equalsIgnoreCase(typeName)) {
+            return TYPE_UNSET;
+        } else if ("boolean".equalsIgnoreCase(typeName)) {
+            return TYPE_BOOLEAN;
+        } else if ("byte".equalsIgnoreCase(typeName)) {
+            return TYPE_BYTE;
+        } else if ("short".equalsIgnoreCase(typeName)) {
+            return TYPE_SHORT;
+        } else if ("int".equalsIgnoreCase(typeName)) {
+            return TYPE_INT;
+        } else if ("long".equalsIgnoreCase(typeName)) {
+            return TYPE_LONG;
+        } else if ("float".equalsIgnoreCase(typeName)) {
+            return TYPE_FLOAT;
+        } else if ("double".equalsIgnoreCase(typeName)) {
+            return TYPE_DOUBLE;
+        } else if ("string".equalsIgnoreCase(typeName)) {
+            return TYPE_STRING;
+        }
+        return TYPE_ERROR;
+    }
+
+    /**
+     * Consumes EOL tokens.
+     * Returns when a non-EOL token is found.
+     *
+     * @param st The {@code StreamTokenizer} to read tokens from
+     * @return &gt; 0 if an EOL token was seen, &lt; 0 if EOF was seen,
+     *         0 if no tokens were consumed
+     */
+    static int eatEols(StreamTokenizer st) throws IOException {
+        int token;
+        boolean eolSeen = false;
+        do {
+            token = st.nextToken();
+            if (token == StreamTokenizer.TT_EOF) {
+                return -1;
+            } else if (token == StreamTokenizer.TT_EOL) {
+                eolSeen = true;
+            }
+        } while (token == StreamTokenizer.TT_EOL);
+        st.pushBack();
+        return eolSeen ? 1 : 0;
+    }
+
+    /**
+     * Parses the data in the reader.
+     *
+     * @param r The {@code Reader} containing input data to parse
+     * @param map The {@code Map} to insert parameter values into
+     * @throws ParseException if the input data is malformed
+     * @throws IOException if there is a problem reading from the {@code Reader}
+     */
+    static void parse(Reader r, Map<String, Object> map) throws ParseException, IOException {
+        final StreamTokenizer st = initTokenizer(r);
+
+        /* A property name must be a valid fully-qualified class + package name.
+         * We don't support Unicode, though.
+         */
+        final String identifierPattern = "[a-zA-Z_$][0-9a-zA-Z_$]*";
+        final Pattern propertyNamePattern =
+            Pattern.compile("(" + identifierPattern + "\\.)*" + identifierPattern);
+
+
+        boolean eolNeeded = false;
+        while (true) {
+            int token;
+
+            // Eat one or more EOL, or quit on EOF.
+            int eolStatus = eatEols(st);
+            if (eolStatus < 0) {
+                // EOF occurred.
+                break;
+            } else if (eolNeeded && eolStatus == 0) {
+                throw new ParseException(st, "end of line or end of file");
+            }
+
+            // Read the property name.
+            token = st.nextToken();
+            if (token != StreamTokenizer.TT_WORD) {
+                throw new ParseException(st, "property name");
+            }
+            final String propertyName = st.sval;
+            if (!propertyNamePattern.matcher(propertyName).matches()) {
+                throw new ParseException(st, "valid property name");
+            }
+            st.sval = null;
+
+            // Read the type.
+            token = st.nextToken();
+            if (token != StreamTokenizer.TT_WORD) {
+                throw new ParseException(st, "type name");
+            }
+            final int type = interpretType(st.sval);
+            if (type == TYPE_ERROR) {
+                throw new ParseException(st, "valid type name");
+            }
+            st.sval = null;
+
+            if (type == TYPE_UNSET) {
+                map.remove(propertyName);
+            } else {
+                // Expect '='.
+                token = st.nextToken();
+                if (token != '=') {
+                    throw new ParseException(st, "'='");
+                }
+
+                // Read a value of the appropriate type, and insert into the map.
+                final Object value = parseValue(st, type);
+                final Object oldValue = map.remove(propertyName);
+                if (oldValue != null) {
+                    // TODO: catch the case where a string is set to null and then
+                    //       the same property is defined with a different type.
+                    if (value.getClass() != oldValue.getClass()) {
+                        throw new ParseException(st,
+                            "(property previously declared as a different type)");
+                    }
+                }
+                map.put(propertyName, value);
+            }
+
+            // Require that we see at least one EOL before the next token.
+            eolNeeded = true;
+        }
+    }
+
+    /**
+     * Parses the next token in the StreamTokenizer as the specified type.
+     *
+     * @param st The token source
+     * @param type The type to interpret next token as
+     * @return a Boolean, Number subclass, or String representing the value.
+     *         Null strings are represented by the String instance NULL_STRING
+     * @throws IOException if there is a problem reading from the {@code StreamTokenizer}
+     */
+    static Object parseValue(StreamTokenizer st, final int type) throws IOException {
+        final int token = st.nextToken();
+
+        if (type == TYPE_BOOLEAN) {
+            if (token != StreamTokenizer.TT_WORD) {
+                throw new ParseException(st, "boolean constant");
+            }
+
+            if ("true".equalsIgnoreCase(st.sval)) {
+                return Boolean.TRUE;
+            } else if ("false".equalsIgnoreCase(st.sval)) {
+                return Boolean.FALSE;
+            }
+
+            throw new ParseException(st, "boolean constant");
+        } else if ((type & 0xff) == 'I') {
+            if (token != StreamTokenizer.TT_WORD) {
+                throw new ParseException(st, "integer constant");
+            }
+
+            /* Parse the string.  Long.decode() handles C-style integer constants
+             * ("0x" -> hex, "0" -> octal).  It also treats numbers with a prefix of "#" as
+             * hex, but our syntax intentionally does not list '#' as a word character.
+             */
+            long value;
+            try {
+                value = Long.decode(st.sval);
+            } catch (NumberFormatException ex) {
+                throw new ParseException(st, "integer constant");
+            }
+
+            // Ensure that the type can hold this value, and return.
+            int width = (type >> 8) & 0xff;
+            switch (width) {
+            case 1:
+                if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+                    throw new ParseException(st, "8-bit integer constant");
+                }
+                return new Byte((byte)value);
+            case 2:
+                if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+                    throw new ParseException(st, "16-bit integer constant");
+                }
+                return new Short((short)value);
+            case 4:
+                if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
+                    throw new ParseException(st, "32-bit integer constant");
+                }
+                return new Integer((int)value);
+            case 8:
+                if (value < Long.MIN_VALUE || value > Long.MAX_VALUE) {
+                    throw new ParseException(st, "64-bit integer constant");
+                }
+                return new Long(value);
+            default:
+                throw new IllegalStateException(
+                    "Internal error; unexpected integer type width " + width);
+            }
+        } else if ((type & 0xff) == 'F') {
+            if (token != StreamTokenizer.TT_WORD) {
+                throw new ParseException(st, "float constant");
+            }
+
+            // Parse the string.
+            /* TODO: Maybe just parse as float or double, losing precision if necessary.
+             *       Parsing as double and converting to float can change the value
+             *       compared to just parsing as float.
+             */
+            double value;
+            try {
+                /* TODO: detect if the string representation loses precision
+                 *       when being converted to a double.
+                 */
+                value = Double.parseDouble(st.sval);
+            } catch (NumberFormatException ex) {
+                throw new ParseException(st, "float constant");
+            }
+
+            // Ensure that the type can hold this value, and return.
+            if (((type >> 8) & 0xff) == 4) {
+                // This property is a float; make sure the value fits.
+                double absValue = Math.abs(value);
+                if (absValue != 0.0 && !Double.isInfinite(value) && !Double.isNaN(value)) {
+                    if (absValue < Float.MIN_VALUE || absValue > Float.MAX_VALUE) {
+                        throw new ParseException(st, "32-bit float constant");
+                    }
+                }
+                return new Float((float)value);
+            } else {
+                // This property is a double; no need to truncate.
+                return new Double(value);
+            }
+        } else if (type == TYPE_STRING) {
+            // Expect a quoted string or the word "null".
+            if (token == '"') {
+                return st.sval;
+            } else if (token == StreamTokenizer.TT_WORD && "null".equalsIgnoreCase(st.sval)) {
+                return NULL_STRING;
+            }
+            throw new ParseException(st, "double-quoted string or 'null'");
+        }
+
+        throw new IllegalStateException("Internal error; unknown type " + type);
+    }
+
+
+    /**
+     * Creates an empty TypedProperties instance.
+     */
+    public TypedProperties() {
+        super();
+    }
+
+    /**
+     * Loads zero or more properties from the specified Reader.
+     * Properties that have already been loaded are preserved unless
+     * the new Reader overrides or unsets earlier values for the
+     * same properties.
+     *
+     * File syntax:
+     *
+     *     &lt;property-name&gt; &lt;type&gt; = &lt;value&gt;
+     *     &lt;property-name&gt; unset
+     *
+     *     '#' is a comment character; it and anything appearing after it
+     *     on the line is ignored.
+     *
+     *     Blank lines are ignored.
+     *
+     *     The only required whitespace is between the property name
+     *     and the type.
+     *
+     *     Property assignments may not be split across multiple lines.
+     *
+     *     &lt;property-name&gt; is a valid fully-qualified class name
+     *     (one or more valid identifiers separated by dot characters).
+     *
+     *     &lt;type&gt; is one of {boolean, byte, short, int, long,
+     *     float, double, string}, and is case-insensitive.
+     *
+     *     &lt;value&gt; depends on the type:
+     *     - boolean: one of {true, false} (case-insensitive)
+     *     - byte, short, int, long: a valid Java integer constant
+     *       (including non-base-10 constants like 0xabc and 074)
+     *       whose value does not overflow the type.  NOTE: these are
+     *       interpreted as Java integer values, so they are all signed.
+     *     - float, double: a valid Java floating-point constant.
+     *       If the type is float, the value must fit in 32 bits.
+     *     - string: a double-quoted string value, or the word {@code null}.
+     *       NOTE: the contents of the string must be 7-bit clean ASCII;
+     *       C-style octal escapes are recognized, but Unicode escapes are not.
+     *
+     *
+     * @param r The Reader to load properties from
+     * @throws IOException if an error occurs when reading the data
+     * @throws IllegalArgumentException if the data is malformed
+     */
+    public void load(Reader r) throws IOException {
+        parse(r, this);
+    }
+
+    @Override
+    public Object get(Object key) {
+        Object value = super.get(key);
+        if (value == NULL_STRING) {
+            return null;
+        }
+        return value;
+    }
+
+    /*
+     * Getters with explicit defaults
+     */
+
+    /**
+     * An unchecked exception that is thrown if a {@code get&lt;TYPE&gt;()} method
+     * is used to retrieve a parameter whose type does not match the method name.
+     */
+    public static class TypeException extends IllegalArgumentException {
+        TypeException(String property, Object value, String requestedType) {
+            super(property + " has type " + value.getClass().getName() +
+                ", not " + requestedType);
+        }
+    }
+
+    /**
+     * Returns the value of a boolean property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a boolean
+     */
+    public boolean getBoolean(String property, boolean def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value instanceof Boolean) {
+            return ((Boolean)value).booleanValue();
+        }
+        throw new TypeException(property, value, "boolean");
+    }
+
+    /**
+     * Returns the value of a byte property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a byte
+     */
+    public byte getByte(String property, byte def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value instanceof Byte) {
+            return ((Byte)value).byteValue();
+        }
+        throw new TypeException(property, value, "byte");
+    }
+
+    /**
+     * Returns the value of a short property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a short
+     */
+    public short getShort(String property, short def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value instanceof Short) {
+            return ((Short)value).shortValue();
+        }
+        throw new TypeException(property, value, "short");
+    }
+
+    /**
+     * Returns the value of an integer property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not an integer
+     */
+    public int getInt(String property, int def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value instanceof Integer) {
+            return ((Integer)value).intValue();
+        }
+        throw new TypeException(property, value, "int");
+    }
+
+    /**
+     * Returns the value of a long property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a long
+     */
+    public long getLong(String property, long def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value instanceof Long) {
+            return ((Long)value).longValue();
+        }
+        throw new TypeException(property, value, "long");
+    }
+
+    /**
+     * Returns the value of a float property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a float
+     */
+    public float getFloat(String property, float def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value instanceof Float) {
+            return ((Float)value).floatValue();
+        }
+        throw new TypeException(property, value, "float");
+    }
+
+    /**
+     * Returns the value of a double property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a double
+     */
+    public double getDouble(String property, double def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value instanceof Double) {
+            return ((Double)value).doubleValue();
+        }
+        throw new TypeException(property, value, "double");
+    }
+
+    /**
+     * Returns the value of a string property, or the default if the property
+     * has not been defined.
+     *
+     * @param property The name of the property to return
+     * @param def The default value to return if the property is not set
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a string
+     */
+    public String getString(String property, String def) {
+        Object value = super.get(property);
+        if (value == null) {
+            return def;
+        }
+        if (value == NULL_STRING) {
+            return null;
+        } else if (value instanceof String) {
+            return (String)value;
+        }
+        throw new TypeException(property, value, "string");
+    }
+
+    /*
+     * Getters with implicit defaults
+     */
+
+    /**
+     * Returns the value of a boolean property, or false
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a boolean
+     */
+    public boolean getBoolean(String property) {
+        return getBoolean(property, false);
+    }
+
+    /**
+     * Returns the value of a byte property, or 0
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a byte
+     */
+    public byte getByte(String property) {
+        return getByte(property, (byte)0);
+    }
+
+    /**
+     * Returns the value of a short property, or 0
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a short
+     */
+    public short getShort(String property) {
+        return getShort(property, (short)0);
+    }
+
+    /**
+     * Returns the value of an integer property, or 0
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not an integer
+     */
+    public int getInt(String property) {
+        return getInt(property, 0);
+    }
+
+    /**
+     * Returns the value of a long property, or 0
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a long
+     */
+    public long getLong(String property) {
+        return getLong(property, 0L);
+    }
+
+    /**
+     * Returns the value of a float property, or 0.0
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a float
+     */
+    public float getFloat(String property) {
+        return getFloat(property, 0.0f);
+    }
+
+    /**
+     * Returns the value of a double property, or 0.0
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a double
+     */
+    public double getDouble(String property) {
+        return getDouble(property, 0.0);
+    }
+
+    /**
+     * Returns the value of a String property, or ""
+     * if the property has not been defined.
+     *
+     * @param property The name of the property to return
+     * @return the value of the property
+     * @throws TypeException if the property is set and is not a string
+     */
+    public String getString(String property) {
+        return getString(property, "");
+    }
+}
diff --git a/core/java/com/google/android/net/GoogleHttpClient.java b/core/java/com/google/android/net/GoogleHttpClient.java
index ac9ad73..871c925 100644
--- a/core/java/com/google/android/net/GoogleHttpClient.java
+++ b/core/java/com/google/android/net/GoogleHttpClient.java
@@ -196,6 +196,12 @@
         }
     }
 
+    public String rewriteURI(String original) {
+        UrlRules rules = UrlRules.getRules(mResolver);
+        UrlRules.Rule rule = rules.matchRule(original);
+        return rule.apply(original);
+    }
+
     public HttpResponse execute(HttpUriRequest request, HttpContext context)
             throws IOException {
         // Rewrite the supplied URL...
@@ -262,7 +268,7 @@
      *
      * @param originalUserAgent to modify (however you identify yourself)
      * @return user agent with a "yes, I really can handle gzip" token added.
-     * @deprecated Use {@link #GoogleHttpClient(android.content.ContentResolver, String, boolean)} 
+     * @deprecated Use {@link #GoogleHttpClient(android.content.ContentResolver, String, boolean)}
      */
     public static String getGzipCapableUserAgent(String originalUserAgent) {
         return originalUserAgent + "; gzip";
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 18f2878..ac35459 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -21,6 +21,10 @@
 	CursorWindow.cpp \
 	com_google_android_gles_jni_EGLImpl.cpp \
 	com_google_android_gles_jni_GLImpl.cpp.arm \
+	android_opengl_GLES10.cpp \
+	android_opengl_GLES10Ext.cpp \
+	android_opengl_GLES11.cpp \
+	android_opengl_GLES11Ext.cpp \
 	android_database_CursorWindow.cpp \
 	android_database_SQLiteDebug.cpp \
 	android_database_SQLiteDatabase.cpp \
@@ -125,6 +129,7 @@
 	external/skia/include/core \
 	external/skia/include/effects \
 	external/skia/include/images \
+	external/skia/src/ports \
 	external/skia/include/utils \
 	external/sqlite/dist \
 	external/sqlite/android \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f4643f4..7c9f457 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -30,6 +30,7 @@
 
 #include <SkGraphics.h>
 #include <SkImageDecoder.h>
+#include <SkImageRef_GlobalPool.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
@@ -66,6 +67,10 @@
 
 extern int register_com_google_android_gles_jni_EGLImpl(JNIEnv* env);
 extern int register_com_google_android_gles_jni_GLImpl(JNIEnv* env);
+extern int register_android_opengl_jni_GLES10(JNIEnv* env);
+extern int register_android_opengl_jni_GLES10Ext(JNIEnv* env);
+extern int register_android_opengl_jni_GLES11(JNIEnv* env);
+extern int register_android_opengl_jni_GLES11Ext(JNIEnv* env);
 
 extern int register_android_hardware_Camera(JNIEnv *env);
 
@@ -224,6 +229,13 @@
     // this sets our preference for 16bit images during decode
     // in case the src is opaque and 24bit
     SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
+    // This cache is shared between browser native images, and java "purgeable"
+    // bitmaps. This globalpool is for images that do not either use the java
+    // heap, or are not backed by ashmem. See BitmapFactory.cpp for the key
+    // java call site.
+    SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);
+    // There is also a global font cache, but its budget is specified in code
+    // see SkFontHost_android.cpp
 
     // Pre-allocate enough space to hold a fair number of options.
     mOptions.setCapacity(20);
@@ -1042,6 +1054,10 @@
     REG_JNI(register_android_view_ViewRoot),
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
     REG_JNI(register_com_google_android_gles_jni_GLImpl),
+    REG_JNI(register_android_opengl_jni_GLES10),
+    REG_JNI(register_android_opengl_jni_GLES10Ext),
+    REG_JNI(register_android_opengl_jni_GLES11),
+    REG_JNI(register_android_opengl_jni_GLES11Ext),
 
     REG_JNI(register_android_graphics_Bitmap),
     REG_JNI(register_android_graphics_BitmapFactory),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 332b01c..1fd15d6 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -1,6 +1,8 @@
 #define LOG_TAG "BitmapFactory"
 
 #include "SkImageDecoder.h"
+#include "SkImageRef_ashmem.h"
+#include "SkImageRef_GlobalPool.h"
 #include "SkPixelRef.h"
 #include "SkStream.h"
 #include "GraphicsJNI.h"
@@ -19,9 +21,12 @@
 static jfieldID gOptions_sampleSizeFieldID;
 static jfieldID gOptions_configFieldID;
 static jfieldID gOptions_ditherFieldID;
+static jfieldID gOptions_purgeableFieldID;
+static jfieldID gOptions_shareableFieldID;
 static jfieldID gOptions_widthFieldID;
 static jfieldID gOptions_heightFieldID;
 static jfieldID gOptions_mimeFieldID;
+static jfieldID gOptions_mCancelID;
 
 static jclass gFileDescriptor_class;
 static jfieldID gFileDescriptor_descriptor;
@@ -32,8 +37,6 @@
     #define TRACE_BITMAP(code)
 #endif
 
-//#define MIN_SIZE_TO_USE_MMAP    (4*1024)
-
 ///////////////////////////////////////////////////////////////////////////////
 
 class AutoDecoderCancel {
@@ -204,12 +207,16 @@
 public:
     AssetStreamAdaptor(Asset* a) : fAsset(a) {}
     
-	virtual bool rewind() {
+    virtual bool rewind() {
         off_t pos = fAsset->seek(0, SEEK_SET);
-        return pos != (off_t)-1;
+        if (pos == (off_t)-1) {
+            SkDebugf("----- fAsset->seek(rewind) failed\n");
+            return false;
+        }
+        return true;
     }
     
-	virtual size_t read(void* buffer, size_t size) {
+    virtual size_t read(void* buffer, size_t size) {
         ssize_t amount;
         
         if (NULL == buffer) {
@@ -221,15 +228,20 @@
 
             off_t oldOffset = fAsset->seek(0, SEEK_CUR);
             if (-1 == oldOffset) {
+                SkDebugf("---- fAsset->seek(oldOffset) failed\n");
                 return 0;
             }
             off_t newOffset = fAsset->seek(size, SEEK_CUR);
             if (-1 == newOffset) {
+                SkDebugf("---- fAsset->seek(%d) failed\n", size);
                 return 0;
             }
             amount = newOffset - oldOffset;
         } else {
             amount = fAsset->read(buffer, size);
+            if (amount <= 0) {
+                SkDebugf("---- fAsset->read(%d) returned %d\n", size, amount);
+            }
         }
         
         if (amount < 0) {
@@ -278,13 +290,46 @@
     return jstr;
 }
 
-static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
-                        jobject options) {
+static bool optionsPurgeable(JNIEnv* env, jobject options) {
+    return options != NULL &&
+            env->GetBooleanField(options, gOptions_purgeableFieldID);
+}
 
+static bool optionsShareable(JNIEnv* env, jobject options) {
+    return options != NULL &&
+            env->GetBooleanField(options, gOptions_shareableFieldID);
+}
+
+static jobject nullObjectReturn(const char msg[]) {
+    if (msg) {
+        SkDebugf("--- %s\n", msg);
+    }
+    return NULL;
+}
+
+static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
+                                   int sampleSize) {
+    SkPixelRef* pr;
+    // only use ashmem for large images, since mmaps come at a price
+    if (bitmap->getSize() >= 32 * 65536) {
+        pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize);
+    } else {
+        pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize);
+    }
+    bitmap->setPixelRef(pr)->unref();
+    return pr;
+}
+
+// since we "may" create a purgeable imageref, we require the stream be ref'able
+// i.e. dynamically allocated, since its lifetime may exceed the current stack
+// frame.
+static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
+                        jobject options, bool allowPurgeable) {
     int sampleSize = 1;
     SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode;
     SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
     bool doDither = true;
+    bool isPurgeable = allowPurgeable && optionsPurgeable(env, options);
     
     if (NULL != options) {
         sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
@@ -303,14 +348,14 @@
 
     SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
     if (NULL == decoder) {
-        return NULL;
+        return nullObjectReturn("SkImageDecoder::Factory returned null");
     }
     
     decoder->setSampleSize(sampleSize);
     decoder->setDitherImage(doDither);
 
     NinePatchPeeker     peeker;
-    JavaPixelAllocator  allocator(env);
+    JavaPixelAllocator  javaAllocator(env);
     SkBitmap*           bitmap = new SkBitmap;
     Res_png_9patch      dummy9Patch;
 
@@ -318,14 +363,27 @@
     SkAutoTDelete<SkBitmap>         adb(bitmap);
 
     decoder->setPeeker(&peeker);
-    decoder->setAllocator(&allocator);
-    
+    if (!isPurgeable) {
+        decoder->setAllocator(&javaAllocator);
+    }
+
     AutoDecoderCancel   adc(options, decoder);
 
-    if (!decoder->decode(stream, bitmap, prefConfig, mode)) {
-        return NULL;
+    // To fix the race condition in case "requestCancelDecode"
+    // happens earlier than AutoDecoderCancel object is added
+    // to the gAutoDecoderCancelMutex linked list.
+    if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
+        return nullObjectReturn("gOptions_mCancelID");;
     }
-    
+
+    SkImageDecoder::Mode decodeMode = mode;
+    if (isPurgeable) {
+        decodeMode = SkImageDecoder::kDecodeBounds_Mode;
+    }
+    if (!decoder->decode(stream, bitmap, prefConfig, decodeMode)) {
+        return nullObjectReturn("decoder->decode returned false");
+    }
+
     // update options (if any)
     if (NULL != options) {
         env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
@@ -336,7 +394,7 @@
         env->SetObjectField(options, gOptions_mimeFieldID,
                             getMimeTypeString(env, decoder->getFormat()));
     }
-    
+
     // if we're in justBounds mode, return now (skip the java bitmap)
     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
         return NULL;
@@ -347,12 +405,12 @@
         size_t ninePatchArraySize = peeker.fPatch->serializedSize();
         ninePatchChunk = env->NewByteArray(ninePatchArraySize);
         if (NULL == ninePatchChunk) {
-            return NULL;
+            return nullObjectReturn("ninePatchChunk == null");
         }
         jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ninePatchChunk,
                                                               NULL);
         if (NULL == array) {
-            return NULL;
+            return nullObjectReturn("primitive array == null");
         }
         peeker.fPatch->serialize(array);
         env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
@@ -372,12 +430,18 @@
             GraphicsJNI::set_jrect(env, padding, -1, -1, -1, -1);
         }
     }
-    
-    // promise we will never change our pixels (great for sharing and pictures)
-    SkPixelRef* ref = bitmap->pixelRef();
-    SkASSERT(ref);
-    ref->setImmutable();
 
+    SkPixelRef* pr;
+    if (isPurgeable) {
+        pr = installPixelRef(bitmap, stream, sampleSize);
+    } else {
+        // if we get here, we're in kDecodePixels_Mode and will therefore
+        // already have a pixelref installed.
+        pr = bitmap->pixelRef();
+    }
+    // promise we will never change our pixels (great for sharing and pictures)
+    pr->setImmutable();
+    // now create the java bitmap
     return GraphicsJNI::createBitmap(env, bitmap, false, ninePatchChunk);
 }
 
@@ -390,7 +454,8 @@
     SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage);
 
     if (stream) {
-        bitmap = doDecode(env, stream, padding, options);
+        // for now we don't allow purgeable with java inputstreams
+        bitmap = doDecode(env, stream, padding, options, false);
         stream->unref();
     }
     return bitmap;
@@ -431,52 +496,96 @@
 
     jint descriptor = env->GetIntField(fileDescriptor,
                                        gFileDescriptor_descriptor);
-    
-#ifdef MIN_SIZE_TO_USE_MMAP
-    // First try to use mmap
-    size_t size = getFDSize(descriptor);
-    if (size >= MIN_SIZE_TO_USE_MMAP) {
-        void* addr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, descriptor, 0);
-//        SkDebugf("-------- mmap returned %p %d\n", addr, size);
-        if (MAP_FAILED != addr) {
-            SkMemoryStream strm(addr, size);
-            jobject obj = doDecode(env, &strm, padding, bitmapFactoryOptions);
-            munmap(addr, size);
-            return obj;
+
+    bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions);
+    bool isShareable = optionsShareable(env, bitmapFactoryOptions);
+    bool weOwnTheFD = false;
+    if (isPurgeable && isShareable) {
+        int newFD = ::dup(descriptor);
+        if (-1 != newFD) {
+            weOwnTheFD = true;
+            descriptor = newFD;
         }
     }
-#endif
 
-    // we pass false for closeWhenDone, since the caller owns the descriptor    
-    SkFDStream file(descriptor, false);
-    if (!file.isValid()) {
+    SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD);
+    SkAutoUnref aur(stream);
+    if (!stream->isValid()) {
         return NULL;
     }
-    
-    /* Restore our offset when we leave, so the caller doesn't have to.
-       This is a real feature, so we can be called more than once with the
-       same descriptor.
+
+    /* Restore our offset when we leave, so we can be called more than once
+       with the same descriptor. This is only required if we didn't dup the
+       file descriptor, but it is OK to do it all the time.
     */
     AutoFDSeek as(descriptor);
 
-    return doDecode(env, &file, padding, bitmapFactoryOptions);
+    return doDecode(env, stream, padding, bitmapFactoryOptions, true);
+}
+
+/*  make a deep copy of the asset, and return it as a stream, or NULL if there
+    was an error.
+ */
+static SkStream* copyAssetToStream(Asset* asset) {
+    // if we could "ref/reopen" the asset, we may not need to copy it here
+    off_t size = asset->seek(0, SEEK_SET);
+    if ((off_t)-1 == size) {
+        SkDebugf("---- copyAsset: asset rewind failed\n");
+        return NULL;
+    }
+
+    size = asset->getLength();
+    if (size <= 0) {
+        SkDebugf("---- copyAsset: asset->getLength() returned %d\n", size);
+        return NULL;
+    }
+
+    SkStream* stream = new SkMemoryStream(size);
+    void* data = const_cast<void*>(stream->getMemoryBase());
+    off_t len = asset->read(data, size);
+    if (len != size) {
+        SkDebugf("---- copyAsset: asset->read(%d) returned %d\n", size, len);
+        delete stream;
+        stream = NULL;
+    }
+    return stream;
 }
 
 static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz,
                                  jint native_asset,    // Asset
                                  jobject padding,       // Rect
                                  jobject options) { // BitmapFactory$Options
-    AssetStreamAdaptor  mystream((Asset*)native_asset);
+    SkStream* stream;
+    Asset* asset = reinterpret_cast<Asset*>(native_asset);
 
-    return doDecode(env, &mystream, padding, options);
+    if (optionsPurgeable(env, options)) {
+        // if we could "ref/reopen" the asset, we may not need to copy it here
+        // and we could assume optionsShareable, since assets are always RO
+        stream = copyAssetToStream(asset);
+        if (NULL == stream) {
+            return NULL;
+        }
+    } else {
+        // since we know we'll be done with the asset when we return, we can
+        // just use a simple wrapper
+        stream = new AssetStreamAdaptor(asset);
+    }
+    SkAutoUnref aur(stream);
+    return doDecode(env, stream, padding, options, true);
 }
 
 static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
                                      int offset, int length, jobject options) {
-    AutoJavaByteArray   ar(env, byteArray);
-    SkMemoryStream  stream(ar.ptr() + offset, length);
-
-    return doDecode(env, &stream, NULL, options);
+    /*  If optionsShareable() we could decide to just wrap the java array and
+        share it, but that means adding a globalref to the java array object
+        and managing its lifetime. For now we just always copy the array's data
+        if optionsPurgeable().
+     */
+    AutoJavaByteArray ar(env, byteArray);
+    SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length,
+                                          optionsPurgeable(env, options));
+    SkAutoUnref aur(stream);
+    return doDecode(env, stream, NULL, options, true);
 }
 
 static void nativeRequestCancel(JNIEnv*, jobject joptions) {
@@ -585,9 +694,12 @@
     gOptions_configFieldID = getFieldIDCheck(env, gOptions_class, "inPreferredConfig",
             "Landroid/graphics/Bitmap$Config;");
     gOptions_ditherFieldID = getFieldIDCheck(env, gOptions_class, "inDither", "Z");
+    gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z");
+    gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z");
     gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I");
     gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I");
     gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;");
+    gOptions_mCancelID = getFieldIDCheck(env, gOptions_class, "mCancel", "Z");
 
     gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
     gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 605e4b8..bd6fea8 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -21,6 +21,8 @@
 #include "SkCanvas.h"
 #include "SkDevice.h"
 #include "SkGLCanvas.h"
+#include "SkGraphics.h"
+#include "SkImageRef_GlobalPool.h"
 #include "SkShader.h"
 #include "SkTemplates.h"
 
@@ -58,8 +60,11 @@
         return new SkGLCanvas;
     }
     
-    static void freeGlCaches(JNIEnv* env, jobject) {
+    static void freeCaches(JNIEnv* env, jobject) {
+        // these are called in no particular order
         SkGLCanvas::DeleteAllTextures();
+        SkImageRef_GlobalPool::SetRAMUsed(0);
+        SkGraphics::SetFontCacheUsed(0);
     }
     
     static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
@@ -933,7 +938,7 @@
         (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
     {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
 
-    {"freeGlCaches", "()V", (void*) SkCanvasGlue::freeGlCaches}
+    {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
 };
 
 #include <android_runtime/AndroidRuntime.h>
diff --git a/core/jni/android_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp
index c81af1ce..0b8a604 100644
--- a/core/jni/android_bluetooth_common.cpp
+++ b/core/jni/android_bluetooth_common.cpp
@@ -46,8 +46,9 @@
 }
 
 typedef struct {
-    void (*user_cb)(DBusMessage *, void *);
+    void (*user_cb)(DBusMessage *, void *, void *);
     void *user;
+    void *nat;
     JNIEnv *env;
 } dbus_async_call_t;
 
@@ -63,7 +64,7 @@
     if (msg) {
         if (req->user_cb) {
             // The user may not deref the message object.
-            req->user_cb(msg, req->user);
+            req->user_cb(msg, req->user, req->nat);
         }
         dbus_message_unref(msg);
     }
@@ -74,11 +75,14 @@
     free(req);
 }
 
-dbus_bool_t dbus_func_args_async_valist(JNIEnv *env,
+static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env,
                                         DBusConnection *conn,
                                         int timeout_ms,
-                                        void (*user_cb)(DBusMessage *, void *),
+                                        void (*user_cb)(DBusMessage *,
+                                                        void *,
+                                                        void*),
                                         void *user,
+                                        void *nat,
                                         const char *path,
                                         const char *ifc,
                                         const char *func,
@@ -111,6 +115,7 @@
         pending->env = env;
         pending->user_cb = user_cb;
         pending->user = user;
+        pending->nat = nat;
         //pending->method = msg;
 
         reply = dbus_connection_send_with_reply(conn, msg,
@@ -132,8 +137,9 @@
 dbus_bool_t dbus_func_args_async(JNIEnv *env,
                                  DBusConnection *conn,
                                  int timeout_ms,
-                                 void (*reply)(DBusMessage *, void *),
+                                 void (*reply)(DBusMessage *, void *, void*),
                                  void *user,
+                                 void *nat,
                                  const char *path,
                                  const char *ifc,
                                  const char *func,
@@ -144,7 +150,7 @@
     va_start(lst, first_arg_type);
     ret = dbus_func_args_async_valist(env, conn,
                                       timeout_ms,
-                                      reply, user,
+                                      reply, user, nat,
                                       path, ifc, func,
                                       first_arg_type, lst);
     va_end(lst);
diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h
index c30ba22..69092dd 100644
--- a/core/jni/android_bluetooth_common.h
+++ b/core/jni/android_bluetooth_common.h
@@ -24,7 +24,9 @@
 #include "utils/Log.h"
 
 #include <errno.h>
+#include <pthread.h>
 #include <stdint.h>
+#include <sys/poll.h>
 
 #ifdef HAVE_BLUETOOTH
 #include <dbus/dbus.h>
@@ -45,6 +47,9 @@
 
 #define BTADDR_SIZE 18   // size of BT address character array (including null)
 
+// size of the dbus event loops pollfd structure, hopefully never to be grown
+#define DEFAULT_INITIAL_POLLFD_COUNT 8
+
 jfieldID get_field(JNIEnv *env,
                    jclass clazz,
                    const char *member,
@@ -63,29 +68,33 @@
 
 struct event_loop_native_data_t {
     DBusConnection *conn;
-    /* These variables are set in waitForAndDispatchEventNative() and are
-       valid only within the scope of this function.  At any other time, they
-       are NULL. */
-    jobject me;
-    JNIEnv *env;
-};
 
-dbus_bool_t dbus_func_args_async_valist(JNIEnv *env,
-                                        DBusConnection *conn,
-                                        int timeout_ms,
-                                        void (*reply)(DBusMessage *, void *),
-                                        void *user,
-                                        const char *path,
-                                        const char *ifc,
-                                        const char *func,
-                                        int first_arg_type,
-                                        va_list args);
+    /* protects the thread */
+    pthread_mutex_t thread_mutex;
+    pthread_t thread;
+    /* our comms socket */
+    /* mem for the list of sockets to listen to */
+    struct pollfd *pollData;
+    int pollMemberCount;
+    int pollDataSize;
+    /* mem for matching set of dbus watch ptrs */
+    DBusWatch **watchData;
+    /* pair of sockets for event loop control, Reader and Writer */
+    int controlFdR;
+    int controlFdW;
+    /* our vm and env Version for future env generation */
+    JavaVM *vm;
+    int envVer;
+    /* reference to our java self */
+    jobject me;
+};
 
 dbus_bool_t dbus_func_args_async(JNIEnv *env,
                                  DBusConnection *conn,
                                  int timeout_ms,
-                                 void (*reply)(DBusMessage *, void *),
+                                 void (*reply)(DBusMessage *, void *, void *),
                                  void *user,
+                                 void *nat,
                                  const char *path,
                                  const char *ifc,
                                  const char *func,
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp
index f0b35e9..bbde8d5 100644
--- a/core/jni/android_location_GpsLocationProvider.cpp
+++ b/core/jni/android_location_GpsLocationProvider.cpp
@@ -31,6 +31,7 @@
 static jmethodID method_reportLocation;
 static jmethodID method_reportStatus;
 static jmethodID method_reportSvStatus;
+static jmethodID method_reportSuplStatus;
 static jmethodID method_xtraDownloadRequest;
 
 static const GpsInterface* sGpsInterface = NULL;
@@ -41,19 +42,22 @@
 static GpsLocation  sGpsLocation;
 static GpsStatus    sGpsStatus;
 static GpsSvStatus  sGpsSvStatus;
+static GpsSuplStatus    sGpsSuplStatus;
 
 // a copy of the data shared by android_location_GpsLocationProvider_wait_for_event
 // and android_location_GpsLocationProvider_read_status
 static GpsLocation  sGpsLocationCopy;
 static GpsStatus    sGpsStatusCopy;
 static GpsSvStatus  sGpsSvStatusCopy;
+static GpsSuplStatus    sGpsSuplStatusCopy;
 
 enum CallbackType {
     kLocation = 1,
     kStatus = 2,
     kSvStatus = 4,
-    kXtraDownloadRequest = 8,
-    kDisableRequest = 16,
+    kSuplStatus = 8,
+    kXtraDownloadRequest = 16,
+    kDisableRequest = 32,
 }; 
 static int sPendingCallbacks;
 
@@ -92,6 +96,17 @@
     pthread_mutex_unlock(&sEventMutex);
 }
 
+static void supl_status_callback(GpsSuplStatus* supl_status)
+{
+    pthread_mutex_lock(&sEventMutex);
+
+    sPendingCallbacks |= kSuplStatus;
+    memcpy(&sGpsSuplStatus, supl_status, sizeof(GpsSuplStatus));
+
+    pthread_cond_signal(&sEventCond);
+    pthread_mutex_unlock(&sEventMutex);
+}
+
 GpsCallbacks sGpsCallbacks = {
     location_callback,
     status_callback,
@@ -111,11 +126,15 @@
     download_request_callback,
 };
 
+GpsSuplCallbacks sGpsSuplCallbacks = {
+    supl_status_callback,
+};
 
 static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
     method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
     method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
     method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
+    method_reportSuplStatus = env->GetMethodID(clazz, "reportSuplStatus", "(I)V");
     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
 }
 
@@ -129,7 +148,13 @@
 {
     if (!sGpsInterface)
         sGpsInterface = gps_get_interface();
-    return (sGpsInterface && sGpsInterface->init(&sGpsCallbacks) == 0);
+    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
+        return false;
+
+    if (!sGpsSuplInterface)
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    if (sGpsSuplInterface)
+        sGpsSuplInterface->init(&sGpsSuplCallbacks);
 }
 
 static void android_location_GpsLocationProvider_disable(JNIEnv* env, jobject obj)
@@ -186,6 +211,7 @@
     memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));
     memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy));
     memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy));
+    memcpy(&sGpsSuplStatusCopy, &sGpsSuplStatus, sizeof(sGpsSuplStatusCopy));
     pthread_mutex_unlock(&sEventMutex);   
 
     if (pendingCallbacks & kLocation) { 
@@ -201,6 +227,9 @@
     if (pendingCallbacks & kSvStatus) {
         env->CallVoidMethod(obj, method_reportSvStatus);
     }
+    if (pendingCallbacks & kSuplStatus) {
+        env->CallVoidMethod(obj, method_reportSuplStatus, sGpsSuplStatusCopy.status);
+    }  
     if (pendingCallbacks & kXtraDownloadRequest) {    
         env->CallVoidMethod(obj, method_xtraDownloadRequest);
     }
@@ -269,18 +298,7 @@
     env->ReleaseByteArrayElements(data, bytes, 0);
 }
 
-static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj,
-        jint addr, jint port)
-{
-    if (!sGpsSuplInterface) {
-        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
-    }
-    if (sGpsSuplInterface) {
-        sGpsSuplInterface->set_server(addr, port);
-    }
-}
-
-static void android_location_GpsLocationProvider_set_supl_apn(JNIEnv* env, jobject obj, jstring apn)
+static void android_location_GpsLocationProvider_supl_data_conn_open(JNIEnv* env, jobject obj, jstring apn)
 {
     if (!sGpsSuplInterface) {
         sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
@@ -291,11 +309,42 @@
             return;
         }
         const char *apnStr = env->GetStringUTFChars(apn, NULL);
-        sGpsSuplInterface->set_apn(apnStr);
+        sGpsSuplInterface->data_conn_open(apnStr);
         env->ReleaseStringUTFChars(apn, apnStr);
     }
 }
 
+static void android_location_GpsLocationProvider_supl_data_conn_closed(JNIEnv* env, jobject obj)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        sGpsSuplInterface->data_conn_closed();
+    }
+}
+
+static void android_location_GpsLocationProvider_supl_data_conn_failed(JNIEnv* env, jobject obj)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        sGpsSuplInterface->data_conn_failed();
+    }
+}
+
+static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj,
+        jint addr, jint port)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        sGpsSuplInterface->set_server(addr, port);
+    }
+}
+
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
@@ -312,8 +361,10 @@
 	{"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
 	{"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
 	{"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},
+ 	{"native_supl_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_supl_data_conn_open},
+ 	{"native_supl_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_closed},
+ 	{"native_supl_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_failed},
  	{"native_set_supl_server", "(II)V", (void*)android_location_GpsLocationProvider_set_supl_server},
- 	{"native_set_supl_apn", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_set_supl_apn},
 };
 
 int register_android_location_GpsLocationProvider(JNIEnv* env)
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index fcab813..25670df 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -291,6 +291,7 @@
 {
     return doBooleanCommand("DRIVER RXFILTER-ADD 0", "OK")
 	&& doBooleanCommand("DRIVER RXFILTER-ADD 1", "OK")
+	&& doBooleanCommand("DRIVER RXFILTER-ADD 3", "OK")
 	&& doBooleanCommand("DRIVER RXFILTER-START", "OK");
 }
 
@@ -298,6 +299,7 @@
 {
     jboolean result = doBooleanCommand("DRIVER RXFILTER-STOP", "OK");
     if (result) {
+	(void)doBooleanCommand("DRIVER RXFILTER-REMOVE 3", "OK");
 	(void)doBooleanCommand("DRIVER RXFILTER-REMOVE 1", "OK");
 	(void)doBooleanCommand("DRIVER RXFILTER-REMOVE 0", "OK");
     }
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
new file mode 100644
index 0000000..bc644d2
--- /dev/null
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -0,0 +1,3518 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <GLES/gl.h>
+
+#include <private/opengles/gl_context.h>
+
+#define _NUM_COMPRESSED_TEXTURE_FORMATS \
+        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+
+static int initialized = 0;
+
+static jclass nioAccessClass;
+static jclass bufferClass;
+static jclass OOMEClass;
+static jclass UOEClass;
+static jclass IAEClass;
+static jclass AIOOBEClass;
+static jmethodID getBasePointerID;
+static jmethodID getBaseArrayID;
+static jmethodID getBaseArrayOffsetID;
+static jfieldID positionID;
+static jfieldID limitID;
+static jfieldID elementSizeShiftID;
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInitBuffer(JNIEnv *_env)
+{
+    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
+    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
+
+    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
+    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+
+    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
+            "getBasePointer", "(Ljava/nio/Buffer;)J");
+    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
+    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
+
+    positionID = _env->GetFieldID(bufferClass, "position", "I");
+    limitID = _env->GetFieldID(bufferClass, "limit", "I");
+    elementSizeShiftID =
+        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
+}
+
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    nativeClassInitBuffer(_env);
+
+    jclass IAEClassLocal =
+        _env->FindClass("java/lang/IllegalArgumentException");
+    jclass OOMEClassLocal =
+         _env->FindClass("java/lang/OutOfMemoryError");
+    jclass UOEClassLocal =
+         _env->FindClass("java/lang/UnsupportedOperationException");
+    jclass AIOOBEClassLocal =
+         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
+
+    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
+    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
+    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
+    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
+}
+
+static void *
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+{
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+    jint offset;
+    void *data;
+
+    position = _env->GetIntField(buffer, positionID);
+    limit = _env->GetIntField(buffer, limitID);
+    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    *remaining = (limit - position) << elementSizeShift;
+    pointer = _env->CallStaticLongMethod(nioAccessClass,
+            getBasePointerID, buffer);
+    if (pointer != 0L) {
+        *array = NULL;
+        return (void *) (jint) pointer;
+    }
+    
+    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
+            getBaseArrayID, buffer);
+    offset = _env->CallStaticIntMethod(nioAccessClass,
+            getBaseArrayOffsetID, buffer);
+    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
+    
+    return (void *) ((char *) data + offset);
+}
+
+
+static void
+releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
+{
+    _env->ReleasePrimitiveArrayCritical(array, data,
+					   commit ? 0 : JNI_ABORT);
+}
+
+// --------------------------------------------------------------------------
+
+/* void glActiveTexture ( GLenum texture ) */
+static void
+android_glActiveTexture__I
+  (JNIEnv *_env, jobject _this, jint texture) {
+    glActiveTexture(
+        (GLenum)texture
+    );
+}
+
+/* void glAlphaFunc ( GLenum func, GLclampf ref ) */
+static void
+android_glAlphaFunc__IF
+  (JNIEnv *_env, jobject _this, jint func, jfloat ref) {
+    glAlphaFunc(
+        (GLenum)func,
+        (GLclampf)ref
+    );
+}
+
+/* void glAlphaFuncx ( GLenum func, GLclampx ref ) */
+static void
+android_glAlphaFuncx__II
+  (JNIEnv *_env, jobject _this, jint func, jint ref) {
+    glAlphaFuncx(
+        (GLenum)func,
+        (GLclampx)ref
+    );
+}
+
+/* void glBindTexture ( GLenum target, GLuint texture ) */
+static void
+android_glBindTexture__II
+  (JNIEnv *_env, jobject _this, jint target, jint texture) {
+    glBindTexture(
+        (GLenum)target,
+        (GLuint)texture
+    );
+}
+
+/* void glBlendFunc ( GLenum sfactor, GLenum dfactor ) */
+static void
+android_glBlendFunc__II
+  (JNIEnv *_env, jobject _this, jint sfactor, jint dfactor) {
+    glBlendFunc(
+        (GLenum)sfactor,
+        (GLenum)dfactor
+    );
+}
+
+/* void glClear ( GLbitfield mask ) */
+static void
+android_glClear__I
+  (JNIEnv *_env, jobject _this, jint mask) {
+    glClear(
+        (GLbitfield)mask
+    );
+}
+
+/* void glClearColor ( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) */
+static void
+android_glClearColor__FFFF
+  (JNIEnv *_env, jobject _this, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
+    glClearColor(
+        (GLclampf)red,
+        (GLclampf)green,
+        (GLclampf)blue,
+        (GLclampf)alpha
+    );
+}
+
+/* void glClearColorx ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha ) */
+static void
+android_glClearColorx__IIII
+  (JNIEnv *_env, jobject _this, jint red, jint green, jint blue, jint alpha) {
+    glClearColorx(
+        (GLclampx)red,
+        (GLclampx)green,
+        (GLclampx)blue,
+        (GLclampx)alpha
+    );
+}
+
+/* void glClearDepthf ( GLclampf depth ) */
+static void
+android_glClearDepthf__F
+  (JNIEnv *_env, jobject _this, jfloat depth) {
+    glClearDepthf(
+        (GLclampf)depth
+    );
+}
+
+/* void glClearDepthx ( GLclampx depth ) */
+static void
+android_glClearDepthx__I
+  (JNIEnv *_env, jobject _this, jint depth) {
+    glClearDepthx(
+        (GLclampx)depth
+    );
+}
+
+/* void glClearStencil ( GLint s ) */
+static void
+android_glClearStencil__I
+  (JNIEnv *_env, jobject _this, jint s) {
+    glClearStencil(
+        (GLint)s
+    );
+}
+
+/* void glClientActiveTexture ( GLenum texture ) */
+static void
+android_glClientActiveTexture__I
+  (JNIEnv *_env, jobject _this, jint texture) {
+    glClientActiveTexture(
+        (GLenum)texture
+    );
+}
+
+/* void glColor4f ( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) */
+static void
+android_glColor4f__FFFF
+  (JNIEnv *_env, jobject _this, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
+    glColor4f(
+        (GLfloat)red,
+        (GLfloat)green,
+        (GLfloat)blue,
+        (GLfloat)alpha
+    );
+}
+
+/* void glColor4x ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha ) */
+static void
+android_glColor4x__IIII
+  (JNIEnv *_env, jobject _this, jint red, jint green, jint blue, jint alpha) {
+    glColor4x(
+        (GLfixed)red,
+        (GLfixed)green,
+        (GLfixed)blue,
+        (GLfixed)alpha
+    );
+}
+
+/* void glColorMask ( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ) */
+static void
+android_glColorMask__ZZZZ
+  (JNIEnv *_env, jobject _this, jboolean red, jboolean green, jboolean blue, jboolean alpha) {
+    glColorMask(
+        (GLboolean)red,
+        (GLboolean)green,
+        (GLboolean)blue,
+        (GLboolean)alpha
+    );
+}
+
+/* void glColorPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) */
+static void
+android_glColorPointerBounds__IIILjava_nio_Buffer_2I
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pointer = (GLvoid *) 0;
+
+    pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining);
+    glColorPointerBounds(
+        (GLint)size,
+        (GLenum)type,
+        (GLsizei)stride,
+        (GLvoid *)pointer,
+        (GLsizei)remaining
+    );
+    if (_array) {
+        releasePointer(_env, _array, pointer, JNI_FALSE);
+    }
+}
+
+/* void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) */
+static void
+android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint imageSize, jobject data_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *data = (GLvoid *) 0;
+
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    glCompressedTexImage2D(
+        (GLenum)target,
+        (GLint)level,
+        (GLenum)internalformat,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLint)border,
+        (GLsizei)imageSize,
+        (GLvoid *)data
+    );
+    if (_array) {
+        releasePointer(_env, _array, data, JNI_FALSE);
+    }
+}
+
+/* void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data ) */
+static void
+android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint imageSize, jobject data_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *data = (GLvoid *) 0;
+
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    glCompressedTexSubImage2D(
+        (GLenum)target,
+        (GLint)level,
+        (GLint)xoffset,
+        (GLint)yoffset,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLenum)format,
+        (GLsizei)imageSize,
+        (GLvoid *)data
+    );
+    if (_array) {
+        releasePointer(_env, _array, data, JNI_FALSE);
+    }
+}
+
+/* void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) */
+static void
+android_glCopyTexImage2D__IIIIIIII
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint x, jint y, jint width, jint height, jint border) {
+    glCopyTexImage2D(
+        (GLenum)target,
+        (GLint)level,
+        (GLenum)internalformat,
+        (GLint)x,
+        (GLint)y,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLint)border
+    );
+}
+
+/* void glCopyTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ) */
+static void
+android_glCopyTexSubImage2D__IIIIIIII
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint x, jint y, jint width, jint height) {
+    glCopyTexSubImage2D(
+        (GLenum)target,
+        (GLint)level,
+        (GLint)xoffset,
+        (GLint)yoffset,
+        (GLint)x,
+        (GLint)y,
+        (GLsizei)width,
+        (GLsizei)height
+    );
+}
+
+/* void glCullFace ( GLenum mode ) */
+static void
+android_glCullFace__I
+  (JNIEnv *_env, jobject _this, jint mode) {
+    glCullFace(
+        (GLenum)mode
+    );
+}
+
+/* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
+static void
+android_glDeleteTextures__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    GLuint *textures_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *textures = (GLuint *) 0;
+
+    if (!textures_ref) {
+        _env->ThrowNew(IAEClass, "textures == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(textures_ref) - offset;
+    if (_remaining < n) {
+        _env->ThrowNew(IAEClass, "length - offset < n");
+        goto exit;
+    }
+    textures_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(textures_ref, (jboolean *)0);
+    textures = textures_base + offset;
+
+    glDeleteTextures(
+        (GLsizei)n,
+        (GLuint *)textures
+    );
+
+exit:
+    if (textures_base) {
+        _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
+static void
+android_glDeleteTextures__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLuint *textures = (GLuint *) 0;
+
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    if (_remaining < n) {
+        _env->ThrowNew(IAEClass, "remaining() < n");
+        goto exit;
+    }
+    glDeleteTextures(
+        (GLsizei)n,
+        (GLuint *)textures
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, textures, JNI_FALSE);
+    }
+}
+
+/* void glDepthFunc ( GLenum func ) */
+static void
+android_glDepthFunc__I
+  (JNIEnv *_env, jobject _this, jint func) {
+    glDepthFunc(
+        (GLenum)func
+    );
+}
+
+/* void glDepthMask ( GLboolean flag ) */
+static void
+android_glDepthMask__Z
+  (JNIEnv *_env, jobject _this, jboolean flag) {
+    glDepthMask(
+        (GLboolean)flag
+    );
+}
+
+/* void glDepthRangef ( GLclampf zNear, GLclampf zFar ) */
+static void
+android_glDepthRangef__FF
+  (JNIEnv *_env, jobject _this, jfloat zNear, jfloat zFar) {
+    glDepthRangef(
+        (GLclampf)zNear,
+        (GLclampf)zFar
+    );
+}
+
+/* void glDepthRangex ( GLclampx zNear, GLclampx zFar ) */
+static void
+android_glDepthRangex__II
+  (JNIEnv *_env, jobject _this, jint zNear, jint zFar) {
+    glDepthRangex(
+        (GLclampx)zNear,
+        (GLclampx)zFar
+    );
+}
+
+/* void glDisable ( GLenum cap ) */
+static void
+android_glDisable__I
+  (JNIEnv *_env, jobject _this, jint cap) {
+    glDisable(
+        (GLenum)cap
+    );
+}
+
+/* void glDisableClientState ( GLenum array ) */
+static void
+android_glDisableClientState__I
+  (JNIEnv *_env, jobject _this, jint array) {
+    glDisableClientState(
+        (GLenum)array
+    );
+}
+
+/* void glDrawArrays ( GLenum mode, GLint first, GLsizei count ) */
+static void
+android_glDrawArrays__III
+  (JNIEnv *_env, jobject _this, jint mode, jint first, jint count) {
+    glDrawArrays(
+        (GLenum)mode,
+        (GLint)first,
+        (GLsizei)count
+    );
+}
+
+/* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ) */
+static void
+android_glDrawElements__IIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *indices = (GLvoid *) 0;
+
+    indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
+    if (_remaining < count) {
+        _env->ThrowNew(AIOOBEClass, "remaining() < count");
+        goto exit;
+    }
+    glDrawElements(
+        (GLenum)mode,
+        (GLsizei)count,
+        (GLenum)type,
+        (GLvoid *)indices
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, indices, JNI_FALSE);
+    }
+}
+
+/* void glEnable ( GLenum cap ) */
+static void
+android_glEnable__I
+  (JNIEnv *_env, jobject _this, jint cap) {
+    glEnable(
+        (GLenum)cap
+    );
+}
+
+/* void glEnableClientState ( GLenum array ) */
+static void
+android_glEnableClientState__I
+  (JNIEnv *_env, jobject _this, jint array) {
+    glEnableClientState(
+        (GLenum)array
+    );
+}
+
+/* void glFinish ( void ) */
+static void
+android_glFinish__
+  (JNIEnv *_env, jobject _this) {
+    glFinish();
+}
+
+/* void glFlush ( void ) */
+static void
+android_glFlush__
+  (JNIEnv *_env, jobject _this) {
+    glFlush();
+}
+
+/* void glFogf ( GLenum pname, GLfloat param ) */
+static void
+android_glFogf__IF
+  (JNIEnv *_env, jobject _this, jint pname, jfloat param) {
+    glFogf(
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glFogfv ( GLenum pname, const GLfloat *params ) */
+static void
+android_glFogfv__I_3FI
+  (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_FOG_MODE)
+        case GL_FOG_MODE:
+#endif // defined(GL_FOG_MODE)
+#if defined(GL_FOG_DENSITY)
+        case GL_FOG_DENSITY:
+#endif // defined(GL_FOG_DENSITY)
+#if defined(GL_FOG_START)
+        case GL_FOG_START:
+#endif // defined(GL_FOG_START)
+#if defined(GL_FOG_END)
+        case GL_FOG_END:
+#endif // defined(GL_FOG_END)
+            _needed = 1;
+            break;
+#if defined(GL_FOG_COLOR)
+        case GL_FOG_COLOR:
+#endif // defined(GL_FOG_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glFogfv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glFogfv ( GLenum pname, const GLfloat *params ) */
+static void
+android_glFogfv__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_FOG_MODE)
+        case GL_FOG_MODE:
+#endif // defined(GL_FOG_MODE)
+#if defined(GL_FOG_DENSITY)
+        case GL_FOG_DENSITY:
+#endif // defined(GL_FOG_DENSITY)
+#if defined(GL_FOG_START)
+        case GL_FOG_START:
+#endif // defined(GL_FOG_START)
+#if defined(GL_FOG_END)
+        case GL_FOG_END:
+#endif // defined(GL_FOG_END)
+            _needed = 1;
+            break;
+#if defined(GL_FOG_COLOR)
+        case GL_FOG_COLOR:
+#endif // defined(GL_FOG_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glFogfv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glFogx ( GLenum pname, GLfixed param ) */
+static void
+android_glFogx__II
+  (JNIEnv *_env, jobject _this, jint pname, jint param) {
+    glFogx(
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glFogxv ( GLenum pname, const GLfixed *params ) */
+static void
+android_glFogxv__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_FOG_MODE)
+        case GL_FOG_MODE:
+#endif // defined(GL_FOG_MODE)
+#if defined(GL_FOG_DENSITY)
+        case GL_FOG_DENSITY:
+#endif // defined(GL_FOG_DENSITY)
+#if defined(GL_FOG_START)
+        case GL_FOG_START:
+#endif // defined(GL_FOG_START)
+#if defined(GL_FOG_END)
+        case GL_FOG_END:
+#endif // defined(GL_FOG_END)
+            _needed = 1;
+            break;
+#if defined(GL_FOG_COLOR)
+        case GL_FOG_COLOR:
+#endif // defined(GL_FOG_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glFogxv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glFogxv ( GLenum pname, const GLfixed *params ) */
+static void
+android_glFogxv__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_FOG_MODE)
+        case GL_FOG_MODE:
+#endif // defined(GL_FOG_MODE)
+#if defined(GL_FOG_DENSITY)
+        case GL_FOG_DENSITY:
+#endif // defined(GL_FOG_DENSITY)
+#if defined(GL_FOG_START)
+        case GL_FOG_START:
+#endif // defined(GL_FOG_START)
+#if defined(GL_FOG_END)
+        case GL_FOG_END:
+#endif // defined(GL_FOG_END)
+            _needed = 1;
+            break;
+#if defined(GL_FOG_COLOR)
+        case GL_FOG_COLOR:
+#endif // defined(GL_FOG_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glFogxv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glFrontFace ( GLenum mode ) */
+static void
+android_glFrontFace__I
+  (JNIEnv *_env, jobject _this, jint mode) {
+    glFrontFace(
+        (GLenum)mode
+    );
+}
+
+/* void glFrustumf ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
+static void
+android_glFrustumf__FFFFFF
+  (JNIEnv *_env, jobject _this, jfloat left, jfloat right, jfloat bottom, jfloat top, jfloat zNear, jfloat zFar) {
+    glFrustumf(
+        (GLfloat)left,
+        (GLfloat)right,
+        (GLfloat)bottom,
+        (GLfloat)top,
+        (GLfloat)zNear,
+        (GLfloat)zFar
+    );
+}
+
+/* void glFrustumx ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */
+static void
+android_glFrustumx__IIIIII
+  (JNIEnv *_env, jobject _this, jint left, jint right, jint bottom, jint top, jint zNear, jint zFar) {
+    glFrustumx(
+        (GLfixed)left,
+        (GLfixed)right,
+        (GLfixed)bottom,
+        (GLfixed)top,
+        (GLfixed)zNear,
+        (GLfixed)zFar
+    );
+}
+
+/* void glGenTextures ( GLsizei n, GLuint *textures ) */
+static void
+android_glGenTextures__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray textures_ref, jint offset) {
+    jint _exception = 0;
+    GLuint *textures_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *textures = (GLuint *) 0;
+
+    if (!textures_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "textures == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(textures_ref) - offset;
+    if (_remaining < n) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < n");
+        goto exit;
+    }
+    textures_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(textures_ref, (jboolean *)0);
+    textures = textures_base + offset;
+
+    glGenTextures(
+        (GLsizei)n,
+        (GLuint *)textures
+    );
+
+exit:
+    if (textures_base) {
+        _env->ReleasePrimitiveArrayCritical(textures_ref, textures_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGenTextures ( GLsizei n, GLuint *textures ) */
+static void
+android_glGenTextures__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject textures_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLuint *textures = (GLuint *) 0;
+
+    textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
+    if (_remaining < n) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < n");
+        goto exit;
+    }
+    glGenTextures(
+        (GLsizei)n,
+        (GLuint *)textures
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, textures, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* GLenum glGetError ( void ) */
+static jint
+android_glGetError__
+  (JNIEnv *_env, jobject _this) {
+    GLenum _returnValue;
+    _returnValue = glGetError();
+    return _returnValue;
+}
+
+/* void glGetIntegerv ( GLenum pname, GLint *params ) */
+static void
+android_glGetIntegerv__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_ALPHA_BITS)
+        case GL_ALPHA_BITS:
+#endif // defined(GL_ALPHA_BITS)
+#if defined(GL_ALPHA_TEST_FUNC)
+        case GL_ALPHA_TEST_FUNC:
+#endif // defined(GL_ALPHA_TEST_FUNC)
+#if defined(GL_ALPHA_TEST_REF)
+        case GL_ALPHA_TEST_REF:
+#endif // defined(GL_ALPHA_TEST_REF)
+#if defined(GL_BLEND_DST)
+        case GL_BLEND_DST:
+#endif // defined(GL_BLEND_DST)
+#if defined(GL_BLUE_BITS)
+        case GL_BLUE_BITS:
+#endif // defined(GL_BLUE_BITS)
+#if defined(GL_COLOR_ARRAY_BUFFER_BINDING)
+        case GL_COLOR_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_COLOR_ARRAY_BUFFER_BINDING)
+#if defined(GL_COLOR_ARRAY_SIZE)
+        case GL_COLOR_ARRAY_SIZE:
+#endif // defined(GL_COLOR_ARRAY_SIZE)
+#if defined(GL_COLOR_ARRAY_STRIDE)
+        case GL_COLOR_ARRAY_STRIDE:
+#endif // defined(GL_COLOR_ARRAY_STRIDE)
+#if defined(GL_COLOR_ARRAY_TYPE)
+        case GL_COLOR_ARRAY_TYPE:
+#endif // defined(GL_COLOR_ARRAY_TYPE)
+#if defined(GL_CULL_FACE)
+        case GL_CULL_FACE:
+#endif // defined(GL_CULL_FACE)
+#if defined(GL_DEPTH_BITS)
+        case GL_DEPTH_BITS:
+#endif // defined(GL_DEPTH_BITS)
+#if defined(GL_DEPTH_CLEAR_VALUE)
+        case GL_DEPTH_CLEAR_VALUE:
+#endif // defined(GL_DEPTH_CLEAR_VALUE)
+#if defined(GL_DEPTH_FUNC)
+        case GL_DEPTH_FUNC:
+#endif // defined(GL_DEPTH_FUNC)
+#if defined(GL_DEPTH_WRITEMASK)
+        case GL_DEPTH_WRITEMASK:
+#endif // defined(GL_DEPTH_WRITEMASK)
+#if defined(GL_FOG_DENSITY)
+        case GL_FOG_DENSITY:
+#endif // defined(GL_FOG_DENSITY)
+#if defined(GL_FOG_END)
+        case GL_FOG_END:
+#endif // defined(GL_FOG_END)
+#if defined(GL_FOG_MODE)
+        case GL_FOG_MODE:
+#endif // defined(GL_FOG_MODE)
+#if defined(GL_FOG_START)
+        case GL_FOG_START:
+#endif // defined(GL_FOG_START)
+#if defined(GL_FRONT_FACE)
+        case GL_FRONT_FACE:
+#endif // defined(GL_FRONT_FACE)
+#if defined(GL_GREEN_BITS)
+        case GL_GREEN_BITS:
+#endif // defined(GL_GREEN_BITS)
+#if defined(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES)
+        case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+#endif // defined(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES)
+#if defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES)
+        case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+#endif // defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES)
+#if defined(GL_LIGHT_MODEL_TWO_SIDE)
+        case GL_LIGHT_MODEL_TWO_SIDE:
+#endif // defined(GL_LIGHT_MODEL_TWO_SIDE)
+#if defined(GL_LINE_SMOOTH_HINT)
+        case GL_LINE_SMOOTH_HINT:
+#endif // defined(GL_LINE_SMOOTH_HINT)
+#if defined(GL_LINE_WIDTH)
+        case GL_LINE_WIDTH:
+#endif // defined(GL_LINE_WIDTH)
+#if defined(GL_LOGIC_OP_MODE)
+        case GL_LOGIC_OP_MODE:
+#endif // defined(GL_LOGIC_OP_MODE)
+#if defined(GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES)
+        case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES)
+#if defined(GL_MATRIX_INDEX_ARRAY_SIZE_OES)
+        case GL_MATRIX_INDEX_ARRAY_SIZE_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_SIZE_OES)
+#if defined(GL_MATRIX_INDEX_ARRAY_STRIDE_OES)
+        case GL_MATRIX_INDEX_ARRAY_STRIDE_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_STRIDE_OES)
+#if defined(GL_MATRIX_INDEX_ARRAY_TYPE_OES)
+        case GL_MATRIX_INDEX_ARRAY_TYPE_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_TYPE_OES)
+#if defined(GL_MATRIX_MODE)
+        case GL_MATRIX_MODE:
+#endif // defined(GL_MATRIX_MODE)
+#if defined(GL_MAX_CLIP_PLANES)
+        case GL_MAX_CLIP_PLANES:
+#endif // defined(GL_MAX_CLIP_PLANES)
+#if defined(GL_MAX_ELEMENTS_INDICES)
+        case GL_MAX_ELEMENTS_INDICES:
+#endif // defined(GL_MAX_ELEMENTS_INDICES)
+#if defined(GL_MAX_ELEMENTS_VERTICES)
+        case GL_MAX_ELEMENTS_VERTICES:
+#endif // defined(GL_MAX_ELEMENTS_VERTICES)
+#if defined(GL_MAX_LIGHTS)
+        case GL_MAX_LIGHTS:
+#endif // defined(GL_MAX_LIGHTS)
+#if defined(GL_MAX_MODELVIEW_STACK_DEPTH)
+        case GL_MAX_MODELVIEW_STACK_DEPTH:
+#endif // defined(GL_MAX_MODELVIEW_STACK_DEPTH)
+#if defined(GL_MAX_PALETTE_MATRICES_OES)
+        case GL_MAX_PALETTE_MATRICES_OES:
+#endif // defined(GL_MAX_PALETTE_MATRICES_OES)
+#if defined(GL_MAX_PROJECTION_STACK_DEPTH)
+        case GL_MAX_PROJECTION_STACK_DEPTH:
+#endif // defined(GL_MAX_PROJECTION_STACK_DEPTH)
+#if defined(GL_MAX_TEXTURE_SIZE)
+        case GL_MAX_TEXTURE_SIZE:
+#endif // defined(GL_MAX_TEXTURE_SIZE)
+#if defined(GL_MAX_TEXTURE_STACK_DEPTH)
+        case GL_MAX_TEXTURE_STACK_DEPTH:
+#endif // defined(GL_MAX_TEXTURE_STACK_DEPTH)
+#if defined(GL_MAX_TEXTURE_UNITS)
+        case GL_MAX_TEXTURE_UNITS:
+#endif // defined(GL_MAX_TEXTURE_UNITS)
+#if defined(GL_MAX_VERTEX_UNITS_OES)
+        case GL_MAX_VERTEX_UNITS_OES:
+#endif // defined(GL_MAX_VERTEX_UNITS_OES)
+#if defined(GL_MODELVIEW_STACK_DEPTH)
+        case GL_MODELVIEW_STACK_DEPTH:
+#endif // defined(GL_MODELVIEW_STACK_DEPTH)
+#if defined(GL_NORMAL_ARRAY_BUFFER_BINDING)
+        case GL_NORMAL_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_NORMAL_ARRAY_BUFFER_BINDING)
+#if defined(GL_NORMAL_ARRAY_STRIDE)
+        case GL_NORMAL_ARRAY_STRIDE:
+#endif // defined(GL_NORMAL_ARRAY_STRIDE)
+#if defined(GL_NORMAL_ARRAY_TYPE)
+        case GL_NORMAL_ARRAY_TYPE:
+#endif // defined(GL_NORMAL_ARRAY_TYPE)
+#if defined(GL_NUM_COMPRESSED_TEXTURE_FORMATS)
+        case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+#endif // defined(GL_NUM_COMPRESSED_TEXTURE_FORMATS)
+#if defined(GL_PACK_ALIGNMENT)
+        case GL_PACK_ALIGNMENT:
+#endif // defined(GL_PACK_ALIGNMENT)
+#if defined(GL_PERSPECTIVE_CORRECTION_HINT)
+        case GL_PERSPECTIVE_CORRECTION_HINT:
+#endif // defined(GL_PERSPECTIVE_CORRECTION_HINT)
+#if defined(GL_POINT_SIZE)
+        case GL_POINT_SIZE:
+#endif // defined(GL_POINT_SIZE)
+#if defined(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES)
+        case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+#endif // defined(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES)
+#if defined(GL_POINT_SIZE_ARRAY_STRIDE_OES)
+        case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+#endif // defined(GL_POINT_SIZE_ARRAY_STRIDE_OES)
+#if defined(GL_POINT_SIZE_ARRAY_TYPE_OES)
+        case GL_POINT_SIZE_ARRAY_TYPE_OES:
+#endif // defined(GL_POINT_SIZE_ARRAY_TYPE_OES)
+#if defined(GL_POINT_SMOOTH_HINT)
+        case GL_POINT_SMOOTH_HINT:
+#endif // defined(GL_POINT_SMOOTH_HINT)
+#if defined(GL_POLYGON_OFFSET_FACTOR)
+        case GL_POLYGON_OFFSET_FACTOR:
+#endif // defined(GL_POLYGON_OFFSET_FACTOR)
+#if defined(GL_POLYGON_OFFSET_UNITS)
+        case GL_POLYGON_OFFSET_UNITS:
+#endif // defined(GL_POLYGON_OFFSET_UNITS)
+#if defined(GL_PROJECTION_STACK_DEPTH)
+        case GL_PROJECTION_STACK_DEPTH:
+#endif // defined(GL_PROJECTION_STACK_DEPTH)
+#if defined(GL_RED_BITS)
+        case GL_RED_BITS:
+#endif // defined(GL_RED_BITS)
+#if defined(GL_SHADE_MODEL)
+        case GL_SHADE_MODEL:
+#endif // defined(GL_SHADE_MODEL)
+#if defined(GL_STENCIL_BITS)
+        case GL_STENCIL_BITS:
+#endif // defined(GL_STENCIL_BITS)
+#if defined(GL_STENCIL_CLEAR_VALUE)
+        case GL_STENCIL_CLEAR_VALUE:
+#endif // defined(GL_STENCIL_CLEAR_VALUE)
+#if defined(GL_STENCIL_FAIL)
+        case GL_STENCIL_FAIL:
+#endif // defined(GL_STENCIL_FAIL)
+#if defined(GL_STENCIL_FUNC)
+        case GL_STENCIL_FUNC:
+#endif // defined(GL_STENCIL_FUNC)
+#if defined(GL_STENCIL_PASS_DEPTH_FAIL)
+        case GL_STENCIL_PASS_DEPTH_FAIL:
+#endif // defined(GL_STENCIL_PASS_DEPTH_FAIL)
+#if defined(GL_STENCIL_PASS_DEPTH_PASS)
+        case GL_STENCIL_PASS_DEPTH_PASS:
+#endif // defined(GL_STENCIL_PASS_DEPTH_PASS)
+#if defined(GL_STENCIL_REF)
+        case GL_STENCIL_REF:
+#endif // defined(GL_STENCIL_REF)
+#if defined(GL_STENCIL_VALUE_MASK)
+        case GL_STENCIL_VALUE_MASK:
+#endif // defined(GL_STENCIL_VALUE_MASK)
+#if defined(GL_STENCIL_WRITEMASK)
+        case GL_STENCIL_WRITEMASK:
+#endif // defined(GL_STENCIL_WRITEMASK)
+#if defined(GL_SUBPIXEL_BITS)
+        case GL_SUBPIXEL_BITS:
+#endif // defined(GL_SUBPIXEL_BITS)
+#if defined(GL_TEXTURE_BINDING_2D)
+        case GL_TEXTURE_BINDING_2D:
+#endif // defined(GL_TEXTURE_BINDING_2D)
+#if defined(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING)
+        case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING)
+#if defined(GL_TEXTURE_COORD_ARRAY_SIZE)
+        case GL_TEXTURE_COORD_ARRAY_SIZE:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_SIZE)
+#if defined(GL_TEXTURE_COORD_ARRAY_STRIDE)
+        case GL_TEXTURE_COORD_ARRAY_STRIDE:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_STRIDE)
+#if defined(GL_TEXTURE_COORD_ARRAY_TYPE)
+        case GL_TEXTURE_COORD_ARRAY_TYPE:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_TYPE)
+#if defined(GL_TEXTURE_STACK_DEPTH)
+        case GL_TEXTURE_STACK_DEPTH:
+#endif // defined(GL_TEXTURE_STACK_DEPTH)
+#if defined(GL_UNPACK_ALIGNMENT)
+        case GL_UNPACK_ALIGNMENT:
+#endif // defined(GL_UNPACK_ALIGNMENT)
+#if defined(GL_VERTEX_ARRAY_BUFFER_BINDING)
+        case GL_VERTEX_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_VERTEX_ARRAY_BUFFER_BINDING)
+#if defined(GL_VERTEX_ARRAY_SIZE)
+        case GL_VERTEX_ARRAY_SIZE:
+#endif // defined(GL_VERTEX_ARRAY_SIZE)
+#if defined(GL_VERTEX_ARRAY_STRIDE)
+        case GL_VERTEX_ARRAY_STRIDE:
+#endif // defined(GL_VERTEX_ARRAY_STRIDE)
+#if defined(GL_VERTEX_ARRAY_TYPE)
+        case GL_VERTEX_ARRAY_TYPE:
+#endif // defined(GL_VERTEX_ARRAY_TYPE)
+#if defined(GL_WEIGHT_ARRAY_BUFFER_BINDING_OES)
+        case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES:
+#endif // defined(GL_WEIGHT_ARRAY_BUFFER_BINDING_OES)
+#if defined(GL_WEIGHT_ARRAY_SIZE_OES)
+        case GL_WEIGHT_ARRAY_SIZE_OES:
+#endif // defined(GL_WEIGHT_ARRAY_SIZE_OES)
+#if defined(GL_WEIGHT_ARRAY_STRIDE_OES)
+        case GL_WEIGHT_ARRAY_STRIDE_OES:
+#endif // defined(GL_WEIGHT_ARRAY_STRIDE_OES)
+#if defined(GL_WEIGHT_ARRAY_TYPE_OES)
+        case GL_WEIGHT_ARRAY_TYPE_OES:
+#endif // defined(GL_WEIGHT_ARRAY_TYPE_OES)
+            _needed = 1;
+            break;
+#if defined(GL_ALIASED_POINT_SIZE_RANGE)
+        case GL_ALIASED_POINT_SIZE_RANGE:
+#endif // defined(GL_ALIASED_POINT_SIZE_RANGE)
+#if defined(GL_ALIASED_LINE_WIDTH_RANGE)
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+#endif // defined(GL_ALIASED_LINE_WIDTH_RANGE)
+#if defined(GL_DEPTH_RANGE)
+        case GL_DEPTH_RANGE:
+#endif // defined(GL_DEPTH_RANGE)
+#if defined(GL_MAX_VIEWPORT_DIMS)
+        case GL_MAX_VIEWPORT_DIMS:
+#endif // defined(GL_MAX_VIEWPORT_DIMS)
+#if defined(GL_SMOOTH_LINE_WIDTH_RANGE)
+        case GL_SMOOTH_LINE_WIDTH_RANGE:
+#endif // defined(GL_SMOOTH_LINE_WIDTH_RANGE)
+#if defined(GL_SMOOTH_POINT_SIZE_RANGE)
+        case GL_SMOOTH_POINT_SIZE_RANGE:
+#endif // defined(GL_SMOOTH_POINT_SIZE_RANGE)
+            _needed = 2;
+            break;
+#if defined(GL_COLOR_CLEAR_VALUE)
+        case GL_COLOR_CLEAR_VALUE:
+#endif // defined(GL_COLOR_CLEAR_VALUE)
+#if defined(GL_COLOR_WRITEMASK)
+        case GL_COLOR_WRITEMASK:
+#endif // defined(GL_COLOR_WRITEMASK)
+#if defined(GL_SCISSOR_BOX)
+        case GL_SCISSOR_BOX:
+#endif // defined(GL_SCISSOR_BOX)
+#if defined(GL_VIEWPORT)
+        case GL_VIEWPORT:
+#endif // defined(GL_VIEWPORT)
+            _needed = 4;
+            break;
+#if defined(GL_MODELVIEW_MATRIX)
+        case GL_MODELVIEW_MATRIX:
+#endif // defined(GL_MODELVIEW_MATRIX)
+#if defined(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES)
+        case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES:
+#endif // defined(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES)
+#if defined(GL_PROJECTION_MATRIX)
+        case GL_PROJECTION_MATRIX:
+#endif // defined(GL_PROJECTION_MATRIX)
+#if defined(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES)
+        case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES:
+#endif // defined(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES)
+#if defined(GL_TEXTURE_MATRIX)
+        case GL_TEXTURE_MATRIX:
+#endif // defined(GL_TEXTURE_MATRIX)
+#if defined(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES)
+        case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES:
+#endif // defined(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES)
+            _needed = 16;
+            break;
+#if defined(GL_COMPRESSED_TEXTURE_FORMATS)
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+#endif // defined(GL_COMPRESSED_TEXTURE_FORMATS)
+#if defined(GL_FOG_COLOR)
+        case GL_FOG_COLOR:
+#endif // defined(GL_FOG_COLOR)
+#if defined(GL_LIGHT_MODEL_AMBIENT)
+        case GL_LIGHT_MODEL_AMBIENT:
+#endif // defined(GL_LIGHT_MODEL_AMBIENT)
+            _needed = _NUM_COMPRESSED_TEXTURE_FORMATS;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetIntegerv(
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetIntegerv ( GLenum pname, GLint *params ) */
+static void
+android_glGetIntegerv__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_ALPHA_BITS)
+        case GL_ALPHA_BITS:
+#endif // defined(GL_ALPHA_BITS)
+#if defined(GL_ALPHA_TEST_FUNC)
+        case GL_ALPHA_TEST_FUNC:
+#endif // defined(GL_ALPHA_TEST_FUNC)
+#if defined(GL_ALPHA_TEST_REF)
+        case GL_ALPHA_TEST_REF:
+#endif // defined(GL_ALPHA_TEST_REF)
+#if defined(GL_BLEND_DST)
+        case GL_BLEND_DST:
+#endif // defined(GL_BLEND_DST)
+#if defined(GL_BLUE_BITS)
+        case GL_BLUE_BITS:
+#endif // defined(GL_BLUE_BITS)
+#if defined(GL_COLOR_ARRAY_BUFFER_BINDING)
+        case GL_COLOR_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_COLOR_ARRAY_BUFFER_BINDING)
+#if defined(GL_COLOR_ARRAY_SIZE)
+        case GL_COLOR_ARRAY_SIZE:
+#endif // defined(GL_COLOR_ARRAY_SIZE)
+#if defined(GL_COLOR_ARRAY_STRIDE)
+        case GL_COLOR_ARRAY_STRIDE:
+#endif // defined(GL_COLOR_ARRAY_STRIDE)
+#if defined(GL_COLOR_ARRAY_TYPE)
+        case GL_COLOR_ARRAY_TYPE:
+#endif // defined(GL_COLOR_ARRAY_TYPE)
+#if defined(GL_CULL_FACE)
+        case GL_CULL_FACE:
+#endif // defined(GL_CULL_FACE)
+#if defined(GL_DEPTH_BITS)
+        case GL_DEPTH_BITS:
+#endif // defined(GL_DEPTH_BITS)
+#if defined(GL_DEPTH_CLEAR_VALUE)
+        case GL_DEPTH_CLEAR_VALUE:
+#endif // defined(GL_DEPTH_CLEAR_VALUE)
+#if defined(GL_DEPTH_FUNC)
+        case GL_DEPTH_FUNC:
+#endif // defined(GL_DEPTH_FUNC)
+#if defined(GL_DEPTH_WRITEMASK)
+        case GL_DEPTH_WRITEMASK:
+#endif // defined(GL_DEPTH_WRITEMASK)
+#if defined(GL_FOG_DENSITY)
+        case GL_FOG_DENSITY:
+#endif // defined(GL_FOG_DENSITY)
+#if defined(GL_FOG_END)
+        case GL_FOG_END:
+#endif // defined(GL_FOG_END)
+#if defined(GL_FOG_MODE)
+        case GL_FOG_MODE:
+#endif // defined(GL_FOG_MODE)
+#if defined(GL_FOG_START)
+        case GL_FOG_START:
+#endif // defined(GL_FOG_START)
+#if defined(GL_FRONT_FACE)
+        case GL_FRONT_FACE:
+#endif // defined(GL_FRONT_FACE)
+#if defined(GL_GREEN_BITS)
+        case GL_GREEN_BITS:
+#endif // defined(GL_GREEN_BITS)
+#if defined(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES)
+        case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES:
+#endif // defined(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES)
+#if defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES)
+        case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES:
+#endif // defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES)
+#if defined(GL_LIGHT_MODEL_TWO_SIDE)
+        case GL_LIGHT_MODEL_TWO_SIDE:
+#endif // defined(GL_LIGHT_MODEL_TWO_SIDE)
+#if defined(GL_LINE_SMOOTH_HINT)
+        case GL_LINE_SMOOTH_HINT:
+#endif // defined(GL_LINE_SMOOTH_HINT)
+#if defined(GL_LINE_WIDTH)
+        case GL_LINE_WIDTH:
+#endif // defined(GL_LINE_WIDTH)
+#if defined(GL_LOGIC_OP_MODE)
+        case GL_LOGIC_OP_MODE:
+#endif // defined(GL_LOGIC_OP_MODE)
+#if defined(GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES)
+        case GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES)
+#if defined(GL_MATRIX_INDEX_ARRAY_SIZE_OES)
+        case GL_MATRIX_INDEX_ARRAY_SIZE_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_SIZE_OES)
+#if defined(GL_MATRIX_INDEX_ARRAY_STRIDE_OES)
+        case GL_MATRIX_INDEX_ARRAY_STRIDE_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_STRIDE_OES)
+#if defined(GL_MATRIX_INDEX_ARRAY_TYPE_OES)
+        case GL_MATRIX_INDEX_ARRAY_TYPE_OES:
+#endif // defined(GL_MATRIX_INDEX_ARRAY_TYPE_OES)
+#if defined(GL_MATRIX_MODE)
+        case GL_MATRIX_MODE:
+#endif // defined(GL_MATRIX_MODE)
+#if defined(GL_MAX_CLIP_PLANES)
+        case GL_MAX_CLIP_PLANES:
+#endif // defined(GL_MAX_CLIP_PLANES)
+#if defined(GL_MAX_ELEMENTS_INDICES)
+        case GL_MAX_ELEMENTS_INDICES:
+#endif // defined(GL_MAX_ELEMENTS_INDICES)
+#if defined(GL_MAX_ELEMENTS_VERTICES)
+        case GL_MAX_ELEMENTS_VERTICES:
+#endif // defined(GL_MAX_ELEMENTS_VERTICES)
+#if defined(GL_MAX_LIGHTS)
+        case GL_MAX_LIGHTS:
+#endif // defined(GL_MAX_LIGHTS)
+#if defined(GL_MAX_MODELVIEW_STACK_DEPTH)
+        case GL_MAX_MODELVIEW_STACK_DEPTH:
+#endif // defined(GL_MAX_MODELVIEW_STACK_DEPTH)
+#if defined(GL_MAX_PALETTE_MATRICES_OES)
+        case GL_MAX_PALETTE_MATRICES_OES:
+#endif // defined(GL_MAX_PALETTE_MATRICES_OES)
+#if defined(GL_MAX_PROJECTION_STACK_DEPTH)
+        case GL_MAX_PROJECTION_STACK_DEPTH:
+#endif // defined(GL_MAX_PROJECTION_STACK_DEPTH)
+#if defined(GL_MAX_TEXTURE_SIZE)
+        case GL_MAX_TEXTURE_SIZE:
+#endif // defined(GL_MAX_TEXTURE_SIZE)
+#if defined(GL_MAX_TEXTURE_STACK_DEPTH)
+        case GL_MAX_TEXTURE_STACK_DEPTH:
+#endif // defined(GL_MAX_TEXTURE_STACK_DEPTH)
+#if defined(GL_MAX_TEXTURE_UNITS)
+        case GL_MAX_TEXTURE_UNITS:
+#endif // defined(GL_MAX_TEXTURE_UNITS)
+#if defined(GL_MAX_VERTEX_UNITS_OES)
+        case GL_MAX_VERTEX_UNITS_OES:
+#endif // defined(GL_MAX_VERTEX_UNITS_OES)
+#if defined(GL_MODELVIEW_STACK_DEPTH)
+        case GL_MODELVIEW_STACK_DEPTH:
+#endif // defined(GL_MODELVIEW_STACK_DEPTH)
+#if defined(GL_NORMAL_ARRAY_BUFFER_BINDING)
+        case GL_NORMAL_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_NORMAL_ARRAY_BUFFER_BINDING)
+#if defined(GL_NORMAL_ARRAY_STRIDE)
+        case GL_NORMAL_ARRAY_STRIDE:
+#endif // defined(GL_NORMAL_ARRAY_STRIDE)
+#if defined(GL_NORMAL_ARRAY_TYPE)
+        case GL_NORMAL_ARRAY_TYPE:
+#endif // defined(GL_NORMAL_ARRAY_TYPE)
+#if defined(GL_NUM_COMPRESSED_TEXTURE_FORMATS)
+        case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+#endif // defined(GL_NUM_COMPRESSED_TEXTURE_FORMATS)
+#if defined(GL_PACK_ALIGNMENT)
+        case GL_PACK_ALIGNMENT:
+#endif // defined(GL_PACK_ALIGNMENT)
+#if defined(GL_PERSPECTIVE_CORRECTION_HINT)
+        case GL_PERSPECTIVE_CORRECTION_HINT:
+#endif // defined(GL_PERSPECTIVE_CORRECTION_HINT)
+#if defined(GL_POINT_SIZE)
+        case GL_POINT_SIZE:
+#endif // defined(GL_POINT_SIZE)
+#if defined(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES)
+        case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+#endif // defined(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES)
+#if defined(GL_POINT_SIZE_ARRAY_STRIDE_OES)
+        case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+#endif // defined(GL_POINT_SIZE_ARRAY_STRIDE_OES)
+#if defined(GL_POINT_SIZE_ARRAY_TYPE_OES)
+        case GL_POINT_SIZE_ARRAY_TYPE_OES:
+#endif // defined(GL_POINT_SIZE_ARRAY_TYPE_OES)
+#if defined(GL_POINT_SMOOTH_HINT)
+        case GL_POINT_SMOOTH_HINT:
+#endif // defined(GL_POINT_SMOOTH_HINT)
+#if defined(GL_POLYGON_OFFSET_FACTOR)
+        case GL_POLYGON_OFFSET_FACTOR:
+#endif // defined(GL_POLYGON_OFFSET_FACTOR)
+#if defined(GL_POLYGON_OFFSET_UNITS)
+        case GL_POLYGON_OFFSET_UNITS:
+#endif // defined(GL_POLYGON_OFFSET_UNITS)
+#if defined(GL_PROJECTION_STACK_DEPTH)
+        case GL_PROJECTION_STACK_DEPTH:
+#endif // defined(GL_PROJECTION_STACK_DEPTH)
+#if defined(GL_RED_BITS)
+        case GL_RED_BITS:
+#endif // defined(GL_RED_BITS)
+#if defined(GL_SHADE_MODEL)
+        case GL_SHADE_MODEL:
+#endif // defined(GL_SHADE_MODEL)
+#if defined(GL_STENCIL_BITS)
+        case GL_STENCIL_BITS:
+#endif // defined(GL_STENCIL_BITS)
+#if defined(GL_STENCIL_CLEAR_VALUE)
+        case GL_STENCIL_CLEAR_VALUE:
+#endif // defined(GL_STENCIL_CLEAR_VALUE)
+#if defined(GL_STENCIL_FAIL)
+        case GL_STENCIL_FAIL:
+#endif // defined(GL_STENCIL_FAIL)
+#if defined(GL_STENCIL_FUNC)
+        case GL_STENCIL_FUNC:
+#endif // defined(GL_STENCIL_FUNC)
+#if defined(GL_STENCIL_PASS_DEPTH_FAIL)
+        case GL_STENCIL_PASS_DEPTH_FAIL:
+#endif // defined(GL_STENCIL_PASS_DEPTH_FAIL)
+#if defined(GL_STENCIL_PASS_DEPTH_PASS)
+        case GL_STENCIL_PASS_DEPTH_PASS:
+#endif // defined(GL_STENCIL_PASS_DEPTH_PASS)
+#if defined(GL_STENCIL_REF)
+        case GL_STENCIL_REF:
+#endif // defined(GL_STENCIL_REF)
+#if defined(GL_STENCIL_VALUE_MASK)
+        case GL_STENCIL_VALUE_MASK:
+#endif // defined(GL_STENCIL_VALUE_MASK)
+#if defined(GL_STENCIL_WRITEMASK)
+        case GL_STENCIL_WRITEMASK:
+#endif // defined(GL_STENCIL_WRITEMASK)
+#if defined(GL_SUBPIXEL_BITS)
+        case GL_SUBPIXEL_BITS:
+#endif // defined(GL_SUBPIXEL_BITS)
+#if defined(GL_TEXTURE_BINDING_2D)
+        case GL_TEXTURE_BINDING_2D:
+#endif // defined(GL_TEXTURE_BINDING_2D)
+#if defined(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING)
+        case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING)
+#if defined(GL_TEXTURE_COORD_ARRAY_SIZE)
+        case GL_TEXTURE_COORD_ARRAY_SIZE:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_SIZE)
+#if defined(GL_TEXTURE_COORD_ARRAY_STRIDE)
+        case GL_TEXTURE_COORD_ARRAY_STRIDE:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_STRIDE)
+#if defined(GL_TEXTURE_COORD_ARRAY_TYPE)
+        case GL_TEXTURE_COORD_ARRAY_TYPE:
+#endif // defined(GL_TEXTURE_COORD_ARRAY_TYPE)
+#if defined(GL_TEXTURE_STACK_DEPTH)
+        case GL_TEXTURE_STACK_DEPTH:
+#endif // defined(GL_TEXTURE_STACK_DEPTH)
+#if defined(GL_UNPACK_ALIGNMENT)
+        case GL_UNPACK_ALIGNMENT:
+#endif // defined(GL_UNPACK_ALIGNMENT)
+#if defined(GL_VERTEX_ARRAY_BUFFER_BINDING)
+        case GL_VERTEX_ARRAY_BUFFER_BINDING:
+#endif // defined(GL_VERTEX_ARRAY_BUFFER_BINDING)
+#if defined(GL_VERTEX_ARRAY_SIZE)
+        case GL_VERTEX_ARRAY_SIZE:
+#endif // defined(GL_VERTEX_ARRAY_SIZE)
+#if defined(GL_VERTEX_ARRAY_STRIDE)
+        case GL_VERTEX_ARRAY_STRIDE:
+#endif // defined(GL_VERTEX_ARRAY_STRIDE)
+#if defined(GL_VERTEX_ARRAY_TYPE)
+        case GL_VERTEX_ARRAY_TYPE:
+#endif // defined(GL_VERTEX_ARRAY_TYPE)
+#if defined(GL_WEIGHT_ARRAY_BUFFER_BINDING_OES)
+        case GL_WEIGHT_ARRAY_BUFFER_BINDING_OES:
+#endif // defined(GL_WEIGHT_ARRAY_BUFFER_BINDING_OES)
+#if defined(GL_WEIGHT_ARRAY_SIZE_OES)
+        case GL_WEIGHT_ARRAY_SIZE_OES:
+#endif // defined(GL_WEIGHT_ARRAY_SIZE_OES)
+#if defined(GL_WEIGHT_ARRAY_STRIDE_OES)
+        case GL_WEIGHT_ARRAY_STRIDE_OES:
+#endif // defined(GL_WEIGHT_ARRAY_STRIDE_OES)
+#if defined(GL_WEIGHT_ARRAY_TYPE_OES)
+        case GL_WEIGHT_ARRAY_TYPE_OES:
+#endif // defined(GL_WEIGHT_ARRAY_TYPE_OES)
+            _needed = 1;
+            break;
+#if defined(GL_ALIASED_POINT_SIZE_RANGE)
+        case GL_ALIASED_POINT_SIZE_RANGE:
+#endif // defined(GL_ALIASED_POINT_SIZE_RANGE)
+#if defined(GL_ALIASED_LINE_WIDTH_RANGE)
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+#endif // defined(GL_ALIASED_LINE_WIDTH_RANGE)
+#if defined(GL_DEPTH_RANGE)
+        case GL_DEPTH_RANGE:
+#endif // defined(GL_DEPTH_RANGE)
+#if defined(GL_MAX_VIEWPORT_DIMS)
+        case GL_MAX_VIEWPORT_DIMS:
+#endif // defined(GL_MAX_VIEWPORT_DIMS)
+#if defined(GL_SMOOTH_LINE_WIDTH_RANGE)
+        case GL_SMOOTH_LINE_WIDTH_RANGE:
+#endif // defined(GL_SMOOTH_LINE_WIDTH_RANGE)
+#if defined(GL_SMOOTH_POINT_SIZE_RANGE)
+        case GL_SMOOTH_POINT_SIZE_RANGE:
+#endif // defined(GL_SMOOTH_POINT_SIZE_RANGE)
+            _needed = 2;
+            break;
+#if defined(GL_COLOR_CLEAR_VALUE)
+        case GL_COLOR_CLEAR_VALUE:
+#endif // defined(GL_COLOR_CLEAR_VALUE)
+#if defined(GL_COLOR_WRITEMASK)
+        case GL_COLOR_WRITEMASK:
+#endif // defined(GL_COLOR_WRITEMASK)
+#if defined(GL_SCISSOR_BOX)
+        case GL_SCISSOR_BOX:
+#endif // defined(GL_SCISSOR_BOX)
+#if defined(GL_VIEWPORT)
+        case GL_VIEWPORT:
+#endif // defined(GL_VIEWPORT)
+            _needed = 4;
+            break;
+#if defined(GL_MODELVIEW_MATRIX)
+        case GL_MODELVIEW_MATRIX:
+#endif // defined(GL_MODELVIEW_MATRIX)
+#if defined(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES)
+        case GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES:
+#endif // defined(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES)
+#if defined(GL_PROJECTION_MATRIX)
+        case GL_PROJECTION_MATRIX:
+#endif // defined(GL_PROJECTION_MATRIX)
+#if defined(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES)
+        case GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES:
+#endif // defined(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES)
+#if defined(GL_TEXTURE_MATRIX)
+        case GL_TEXTURE_MATRIX:
+#endif // defined(GL_TEXTURE_MATRIX)
+#if defined(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES)
+        case GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES:
+#endif // defined(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES)
+            _needed = 16;
+            break;
+#if defined(GL_COMPRESSED_TEXTURE_FORMATS)
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+#endif // defined(GL_COMPRESSED_TEXTURE_FORMATS)
+#if defined(GL_FOG_COLOR)
+        case GL_FOG_COLOR:
+#endif // defined(GL_FOG_COLOR)
+#if defined(GL_LIGHT_MODEL_AMBIENT)
+        case GL_LIGHT_MODEL_AMBIENT:
+#endif // defined(GL_LIGHT_MODEL_AMBIENT)
+            _needed = _NUM_COMPRESSED_TEXTURE_FORMATS;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetIntegerv(
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+#include <string.h>
+
+/* const GLubyte * glGetString ( GLenum name ) */
+static
+jstring
+android_glGetString
+  (JNIEnv *_env, jobject _this, jint name) {
+    const char * chars = (const char *)glGetString((GLenum)name);
+    jstring output = _env->NewStringUTF(chars);
+    return output;
+}
+/* void glHint ( GLenum target, GLenum mode ) */
+static void
+android_glHint__II
+  (JNIEnv *_env, jobject _this, jint target, jint mode) {
+    glHint(
+        (GLenum)target,
+        (GLenum)mode
+    );
+}
+
+/* void glLightModelf ( GLenum pname, GLfloat param ) */
+static void
+android_glLightModelf__IF
+  (JNIEnv *_env, jobject _this, jint pname, jfloat param) {
+    glLightModelf(
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glLightModelfv ( GLenum pname, const GLfloat *params ) */
+static void
+android_glLightModelfv__I_3FI
+  (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_LIGHT_MODEL_TWO_SIDE)
+        case GL_LIGHT_MODEL_TWO_SIDE:
+#endif // defined(GL_LIGHT_MODEL_TWO_SIDE)
+            _needed = 1;
+            break;
+#if defined(GL_LIGHT_MODEL_AMBIENT)
+        case GL_LIGHT_MODEL_AMBIENT:
+#endif // defined(GL_LIGHT_MODEL_AMBIENT)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glLightModelfv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLightModelfv ( GLenum pname, const GLfloat *params ) */
+static void
+android_glLightModelfv__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_LIGHT_MODEL_TWO_SIDE)
+        case GL_LIGHT_MODEL_TWO_SIDE:
+#endif // defined(GL_LIGHT_MODEL_TWO_SIDE)
+            _needed = 1;
+            break;
+#if defined(GL_LIGHT_MODEL_AMBIENT)
+        case GL_LIGHT_MODEL_AMBIENT:
+#endif // defined(GL_LIGHT_MODEL_AMBIENT)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glLightModelfv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glLightModelx ( GLenum pname, GLfixed param ) */
+static void
+android_glLightModelx__II
+  (JNIEnv *_env, jobject _this, jint pname, jint param) {
+    glLightModelx(
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glLightModelxv ( GLenum pname, const GLfixed *params ) */
+static void
+android_glLightModelxv__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_LIGHT_MODEL_TWO_SIDE)
+        case GL_LIGHT_MODEL_TWO_SIDE:
+#endif // defined(GL_LIGHT_MODEL_TWO_SIDE)
+            _needed = 1;
+            break;
+#if defined(GL_LIGHT_MODEL_AMBIENT)
+        case GL_LIGHT_MODEL_AMBIENT:
+#endif // defined(GL_LIGHT_MODEL_AMBIENT)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glLightModelxv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLightModelxv ( GLenum pname, const GLfixed *params ) */
+static void
+android_glLightModelxv__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_LIGHT_MODEL_TWO_SIDE)
+        case GL_LIGHT_MODEL_TWO_SIDE:
+#endif // defined(GL_LIGHT_MODEL_TWO_SIDE)
+            _needed = 1;
+            break;
+#if defined(GL_LIGHT_MODEL_AMBIENT)
+        case GL_LIGHT_MODEL_AMBIENT:
+#endif // defined(GL_LIGHT_MODEL_AMBIENT)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glLightModelxv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glLightf ( GLenum light, GLenum pname, GLfloat param ) */
+static void
+android_glLightf__IIF
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jfloat param) {
+    glLightf(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) */
+static void
+android_glLightfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glLightfv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLightfv ( GLenum light, GLenum pname, const GLfloat *params ) */
+static void
+android_glLightfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glLightfv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glLightx ( GLenum light, GLenum pname, GLfixed param ) */
+static void
+android_glLightx__III
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jint param) {
+    glLightx(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) */
+static void
+android_glLightxv__II_3II
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glLightxv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLightxv ( GLenum light, GLenum pname, const GLfixed *params ) */
+static void
+android_glLightxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glLightxv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glLineWidth ( GLfloat width ) */
+static void
+android_glLineWidth__F
+  (JNIEnv *_env, jobject _this, jfloat width) {
+    glLineWidth(
+        (GLfloat)width
+    );
+}
+
+/* void glLineWidthx ( GLfixed width ) */
+static void
+android_glLineWidthx__I
+  (JNIEnv *_env, jobject _this, jint width) {
+    glLineWidthx(
+        (GLfixed)width
+    );
+}
+
+/* void glLoadIdentity ( void ) */
+static void
+android_glLoadIdentity__
+  (JNIEnv *_env, jobject _this) {
+    glLoadIdentity();
+}
+
+/* void glLoadMatrixf ( const GLfloat *m ) */
+static void
+android_glLoadMatrixf___3FI
+  (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    GLfloat *m_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *m = (GLfloat *) 0;
+
+    if (!m_ref) {
+        _env->ThrowNew(IAEClass, "m == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(m_ref) - offset;
+    m_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0);
+    m = m_base + offset;
+
+    glLoadMatrixf(
+        (GLfloat *)m
+    );
+
+exit:
+    if (m_base) {
+        _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLoadMatrixf ( const GLfloat *m ) */
+static void
+android_glLoadMatrixf__Ljava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jobject m_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *m = (GLfloat *) 0;
+
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    glLoadMatrixf(
+        (GLfloat *)m
+    );
+    if (_array) {
+        releasePointer(_env, _array, m, JNI_FALSE);
+    }
+}
+
+/* void glLoadMatrixx ( const GLfixed *m ) */
+static void
+android_glLoadMatrixx___3II
+  (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    GLfixed *m_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    if (!m_ref) {
+        _env->ThrowNew(IAEClass, "m == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(m_ref) - offset;
+    m_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0);
+    m = m_base + offset;
+
+    glLoadMatrixx(
+        (GLfixed *)m
+    );
+
+exit:
+    if (m_base) {
+        _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLoadMatrixx ( const GLfixed *m ) */
+static void
+android_glLoadMatrixx__Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jobject m_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    glLoadMatrixx(
+        (GLfixed *)m
+    );
+    if (_array) {
+        releasePointer(_env, _array, m, JNI_FALSE);
+    }
+}
+
+/* void glLogicOp ( GLenum opcode ) */
+static void
+android_glLogicOp__I
+  (JNIEnv *_env, jobject _this, jint opcode) {
+    glLogicOp(
+        (GLenum)opcode
+    );
+}
+
+/* void glMaterialf ( GLenum face, GLenum pname, GLfloat param ) */
+static void
+android_glMaterialf__IIF
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jfloat param) {
+    glMaterialf(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) */
+static void
+android_glMaterialfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glMaterialfv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params ) */
+static void
+android_glMaterialfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glMaterialfv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glMaterialx ( GLenum face, GLenum pname, GLfixed param ) */
+static void
+android_glMaterialx__III
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jint param) {
+    glMaterialx(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) */
+static void
+android_glMaterialxv__II_3II
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glMaterialxv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params ) */
+static void
+android_glMaterialxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glMaterialxv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glMatrixMode ( GLenum mode ) */
+static void
+android_glMatrixMode__I
+  (JNIEnv *_env, jobject _this, jint mode) {
+    glMatrixMode(
+        (GLenum)mode
+    );
+}
+
+/* void glMultMatrixf ( const GLfloat *m ) */
+static void
+android_glMultMatrixf___3FI
+  (JNIEnv *_env, jobject _this, jfloatArray m_ref, jint offset) {
+    GLfloat *m_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *m = (GLfloat *) 0;
+
+    if (!m_ref) {
+        _env->ThrowNew(IAEClass, "m == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(m_ref) - offset;
+    m_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0);
+    m = m_base + offset;
+
+    glMultMatrixf(
+        (GLfloat *)m
+    );
+
+exit:
+    if (m_base) {
+        _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glMultMatrixf ( const GLfloat *m ) */
+static void
+android_glMultMatrixf__Ljava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jobject m_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *m = (GLfloat *) 0;
+
+    m = (GLfloat *)getPointer(_env, m_buf, &_array, &_remaining);
+    glMultMatrixf(
+        (GLfloat *)m
+    );
+    if (_array) {
+        releasePointer(_env, _array, m, JNI_FALSE);
+    }
+}
+
+/* void glMultMatrixx ( const GLfixed *m ) */
+static void
+android_glMultMatrixx___3II
+  (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    GLfixed *m_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    if (!m_ref) {
+        _env->ThrowNew(IAEClass, "m == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(m_ref) - offset;
+    m_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0);
+    m = m_base + offset;
+
+    glMultMatrixx(
+        (GLfixed *)m
+    );
+
+exit:
+    if (m_base) {
+        _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glMultMatrixx ( const GLfixed *m ) */
+static void
+android_glMultMatrixx__Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jobject m_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    glMultMatrixx(
+        (GLfixed *)m
+    );
+    if (_array) {
+        releasePointer(_env, _array, m, JNI_FALSE);
+    }
+}
+
+/* void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) */
+static void
+android_glMultiTexCoord4f__IFFFF
+  (JNIEnv *_env, jobject _this, jint target, jfloat s, jfloat t, jfloat r, jfloat q) {
+    glMultiTexCoord4f(
+        (GLenum)target,
+        (GLfloat)s,
+        (GLfloat)t,
+        (GLfloat)r,
+        (GLfloat)q
+    );
+}
+
+/* void glMultiTexCoord4x ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q ) */
+static void
+android_glMultiTexCoord4x__IIIII
+  (JNIEnv *_env, jobject _this, jint target, jint s, jint t, jint r, jint q) {
+    glMultiTexCoord4x(
+        (GLenum)target,
+        (GLfixed)s,
+        (GLfixed)t,
+        (GLfixed)r,
+        (GLfixed)q
+    );
+}
+
+/* void glNormal3f ( GLfloat nx, GLfloat ny, GLfloat nz ) */
+static void
+android_glNormal3f__FFF
+  (JNIEnv *_env, jobject _this, jfloat nx, jfloat ny, jfloat nz) {
+    glNormal3f(
+        (GLfloat)nx,
+        (GLfloat)ny,
+        (GLfloat)nz
+    );
+}
+
+/* void glNormal3x ( GLfixed nx, GLfixed ny, GLfixed nz ) */
+static void
+android_glNormal3x__III
+  (JNIEnv *_env, jobject _this, jint nx, jint ny, jint nz) {
+    glNormal3x(
+        (GLfixed)nx,
+        (GLfixed)ny,
+        (GLfixed)nz
+    );
+}
+
+/* void glNormalPointer ( GLenum type, GLsizei stride, const GLvoid *pointer ) */
+static void
+android_glNormalPointerBounds__IILjava_nio_Buffer_2I
+  (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf, jint remaining) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pointer = (GLvoid *) 0;
+
+    pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining);
+    glNormalPointerBounds(
+        (GLenum)type,
+        (GLsizei)stride,
+        (GLvoid *)pointer,
+        (GLsizei)remaining
+    );
+    if (_array) {
+        releasePointer(_env, _array, pointer, JNI_FALSE);
+    }
+}
+
+/* void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
+static void
+android_glOrthof__FFFFFF
+  (JNIEnv *_env, jobject _this, jfloat left, jfloat right, jfloat bottom, jfloat top, jfloat zNear, jfloat zFar) {
+    glOrthof(
+        (GLfloat)left,
+        (GLfloat)right,
+        (GLfloat)bottom,
+        (GLfloat)top,
+        (GLfloat)zNear,
+        (GLfloat)zFar
+    );
+}
+
+/* void glOrthox ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */
+static void
+android_glOrthox__IIIIII
+  (JNIEnv *_env, jobject _this, jint left, jint right, jint bottom, jint top, jint zNear, jint zFar) {
+    glOrthox(
+        (GLfixed)left,
+        (GLfixed)right,
+        (GLfixed)bottom,
+        (GLfixed)top,
+        (GLfixed)zNear,
+        (GLfixed)zFar
+    );
+}
+
+/* void glPixelStorei ( GLenum pname, GLint param ) */
+static void
+android_glPixelStorei__II
+  (JNIEnv *_env, jobject _this, jint pname, jint param) {
+    glPixelStorei(
+        (GLenum)pname,
+        (GLint)param
+    );
+}
+
+/* void glPointSize ( GLfloat size ) */
+static void
+android_glPointSize__F
+  (JNIEnv *_env, jobject _this, jfloat size) {
+    glPointSize(
+        (GLfloat)size
+    );
+}
+
+/* void glPointSizex ( GLfixed size ) */
+static void
+android_glPointSizex__I
+  (JNIEnv *_env, jobject _this, jint size) {
+    glPointSizex(
+        (GLfixed)size
+    );
+}
+
+/* void glPolygonOffset ( GLfloat factor, GLfloat units ) */
+static void
+android_glPolygonOffset__FF
+  (JNIEnv *_env, jobject _this, jfloat factor, jfloat units) {
+    glPolygonOffset(
+        (GLfloat)factor,
+        (GLfloat)units
+    );
+}
+
+/* void glPolygonOffsetx ( GLfixed factor, GLfixed units ) */
+static void
+android_glPolygonOffsetx__II
+  (JNIEnv *_env, jobject _this, jint factor, jint units) {
+    glPolygonOffsetx(
+        (GLfixed)factor,
+        (GLfixed)units
+    );
+}
+
+/* void glPopMatrix ( void ) */
+static void
+android_glPopMatrix__
+  (JNIEnv *_env, jobject _this) {
+    glPopMatrix();
+}
+
+/* void glPushMatrix ( void ) */
+static void
+android_glPushMatrix__
+  (JNIEnv *_env, jobject _this) {
+    glPushMatrix();
+}
+
+/* void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) */
+static void
+android_glReadPixels__IIIIIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pixels = (GLvoid *) 0;
+
+    pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    glReadPixels(
+        (GLint)x,
+        (GLint)y,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLenum)format,
+        (GLenum)type,
+        (GLvoid *)pixels
+    );
+    if (_array) {
+        releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glRotatef ( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) */
+static void
+android_glRotatef__FFFF
+  (JNIEnv *_env, jobject _this, jfloat angle, jfloat x, jfloat y, jfloat z) {
+    glRotatef(
+        (GLfloat)angle,
+        (GLfloat)x,
+        (GLfloat)y,
+        (GLfloat)z
+    );
+}
+
+/* void glRotatex ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z ) */
+static void
+android_glRotatex__IIII
+  (JNIEnv *_env, jobject _this, jint angle, jint x, jint y, jint z) {
+    glRotatex(
+        (GLfixed)angle,
+        (GLfixed)x,
+        (GLfixed)y,
+        (GLfixed)z
+    );
+}
+
+/* void glSampleCoverage ( GLclampf value, GLboolean invert ) */
+static void
+android_glSampleCoverage__FZ
+  (JNIEnv *_env, jobject _this, jfloat value, jboolean invert) {
+    glSampleCoverage(
+        (GLclampf)value,
+        (GLboolean)invert
+    );
+}
+
+/* void glSampleCoveragex ( GLclampx value, GLboolean invert ) */
+static void
+android_glSampleCoveragex__IZ
+  (JNIEnv *_env, jobject _this, jint value, jboolean invert) {
+    glSampleCoveragex(
+        (GLclampx)value,
+        (GLboolean)invert
+    );
+}
+
+/* void glScalef ( GLfloat x, GLfloat y, GLfloat z ) */
+static void
+android_glScalef__FFF
+  (JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z) {
+    glScalef(
+        (GLfloat)x,
+        (GLfloat)y,
+        (GLfloat)z
+    );
+}
+
+/* void glScalex ( GLfixed x, GLfixed y, GLfixed z ) */
+static void
+android_glScalex__III
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint z) {
+    glScalex(
+        (GLfixed)x,
+        (GLfixed)y,
+        (GLfixed)z
+    );
+}
+
+/* void glScissor ( GLint x, GLint y, GLsizei width, GLsizei height ) */
+static void
+android_glScissor__IIII
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height) {
+    glScissor(
+        (GLint)x,
+        (GLint)y,
+        (GLsizei)width,
+        (GLsizei)height
+    );
+}
+
+/* void glShadeModel ( GLenum mode ) */
+static void
+android_glShadeModel__I
+  (JNIEnv *_env, jobject _this, jint mode) {
+    glShadeModel(
+        (GLenum)mode
+    );
+}
+
+/* void glStencilFunc ( GLenum func, GLint ref, GLuint mask ) */
+static void
+android_glStencilFunc__III
+  (JNIEnv *_env, jobject _this, jint func, jint ref, jint mask) {
+    glStencilFunc(
+        (GLenum)func,
+        (GLint)ref,
+        (GLuint)mask
+    );
+}
+
+/* void glStencilMask ( GLuint mask ) */
+static void
+android_glStencilMask__I
+  (JNIEnv *_env, jobject _this, jint mask) {
+    glStencilMask(
+        (GLuint)mask
+    );
+}
+
+/* void glStencilOp ( GLenum fail, GLenum zfail, GLenum zpass ) */
+static void
+android_glStencilOp__III
+  (JNIEnv *_env, jobject _this, jint fail, jint zfail, jint zpass) {
+    glStencilOp(
+        (GLenum)fail,
+        (GLenum)zfail,
+        (GLenum)zpass
+    );
+}
+
+/* void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) */
+static void
+android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pointer = (GLvoid *) 0;
+
+    pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining);
+    glTexCoordPointerBounds(
+        (GLint)size,
+        (GLenum)type,
+        (GLsizei)stride,
+        (GLvoid *)pointer,
+        (GLsizei)remaining
+    );
+    if (_array) {
+        releasePointer(_env, _array, pointer, JNI_FALSE);
+    }
+}
+
+/* void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) */
+static void
+android_glTexEnvf__IIF
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jfloat param) {
+    glTexEnvf(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) */
+static void
+android_glTexEnvfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexEnvfv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params ) */
+static void
+android_glTexEnvfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glTexEnvfv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexEnvx ( GLenum target, GLenum pname, GLfixed param ) */
+static void
+android_glTexEnvx__III
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) {
+    glTexEnvx(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexEnvxv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexEnvxv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexEnvxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glTexEnvxv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) */
+static void
+android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint internalformat, jint width, jint height, jint border, jint format, jint type, jobject pixels_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pixels = (GLvoid *) 0;
+
+    if (pixels_buf) {
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    }
+    glTexImage2D(
+        (GLenum)target,
+        (GLint)level,
+        (GLint)internalformat,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLint)border,
+        (GLenum)format,
+        (GLenum)type,
+        (GLvoid *)pixels
+    );
+    if (_array) {
+        releasePointer(_env, _array, pixels, JNI_FALSE);
+    }
+}
+
+/* void glTexParameterf ( GLenum target, GLenum pname, GLfloat param ) */
+static void
+android_glTexParameterf__IIF
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jfloat param) {
+    glTexParameterf(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glTexParameterx ( GLenum target, GLenum pname, GLfixed param ) */
+static void
+android_glTexParameterx__III
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) {
+    glTexParameterx(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) */
+static void
+android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint xoffset, jint yoffset, jint width, jint height, jint format, jint type, jobject pixels_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pixels = (GLvoid *) 0;
+
+    if (pixels_buf) {
+        pixels = (GLvoid *)getPointer(_env, pixels_buf, &_array, &_remaining);
+    }
+    glTexSubImage2D(
+        (GLenum)target,
+        (GLint)level,
+        (GLint)xoffset,
+        (GLint)yoffset,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLenum)format,
+        (GLenum)type,
+        (GLvoid *)pixels
+    );
+    if (_array) {
+        releasePointer(_env, _array, pixels, JNI_FALSE);
+    }
+}
+
+/* void glTranslatef ( GLfloat x, GLfloat y, GLfloat z ) */
+static void
+android_glTranslatef__FFF
+  (JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z) {
+    glTranslatef(
+        (GLfloat)x,
+        (GLfloat)y,
+        (GLfloat)z
+    );
+}
+
+/* void glTranslatex ( GLfixed x, GLfixed y, GLfixed z ) */
+static void
+android_glTranslatex__III
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint z) {
+    glTranslatex(
+        (GLfixed)x,
+        (GLfixed)y,
+        (GLfixed)z
+    );
+}
+
+/* void glVertexPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) */
+static void
+android_glVertexPointerBounds__IIILjava_nio_Buffer_2I
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf, jint remaining) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pointer = (GLvoid *) 0;
+
+    pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining);
+    glVertexPointerBounds(
+        (GLint)size,
+        (GLenum)type,
+        (GLsizei)stride,
+        (GLvoid *)pointer,
+        (GLsizei)remaining
+    );
+    if (_array) {
+        releasePointer(_env, _array, pointer, JNI_FALSE);
+    }
+}
+
+/* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */
+static void
+android_glViewport__IIII
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint width, jint height) {
+    glViewport(
+        (GLint)x,
+        (GLint)y,
+        (GLsizei)width,
+        (GLsizei)height
+    );
+}
+
+static const char *classPathName = "android/opengl/GLES10";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
+{"glAlphaFunc", "(IF)V", (void *) android_glAlphaFunc__IF },
+{"glAlphaFuncx", "(II)V", (void *) android_glAlphaFuncx__II },
+{"glBindTexture", "(II)V", (void *) android_glBindTexture__II },
+{"glBlendFunc", "(II)V", (void *) android_glBlendFunc__II },
+{"glClear", "(I)V", (void *) android_glClear__I },
+{"glClearColor", "(FFFF)V", (void *) android_glClearColor__FFFF },
+{"glClearColorx", "(IIII)V", (void *) android_glClearColorx__IIII },
+{"glClearDepthf", "(F)V", (void *) android_glClearDepthf__F },
+{"glClearDepthx", "(I)V", (void *) android_glClearDepthx__I },
+{"glClearStencil", "(I)V", (void *) android_glClearStencil__I },
+{"glClientActiveTexture", "(I)V", (void *) android_glClientActiveTexture__I },
+{"glColor4f", "(FFFF)V", (void *) android_glColor4f__FFFF },
+{"glColor4x", "(IIII)V", (void *) android_glColor4x__IIII },
+{"glColorMask", "(ZZZZ)V", (void *) android_glColorMask__ZZZZ },
+{"glColorPointerBounds", "(IIILjava/nio/Buffer;I)V", (void *) android_glColorPointerBounds__IIILjava_nio_Buffer_2I },
+{"glCompressedTexImage2D", "(IIIIIIILjava/nio/Buffer;)V", (void *) android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2 },
+{"glCompressedTexSubImage2D", "(IIIIIIIILjava/nio/Buffer;)V", (void *) android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 },
+{"glCopyTexImage2D", "(IIIIIIII)V", (void *) android_glCopyTexImage2D__IIIIIIII },
+{"glCopyTexSubImage2D", "(IIIIIIII)V", (void *) android_glCopyTexSubImage2D__IIIIIIII },
+{"glCullFace", "(I)V", (void *) android_glCullFace__I },
+{"glDeleteTextures", "(I[II)V", (void *) android_glDeleteTextures__I_3II },
+{"glDeleteTextures", "(ILjava/nio/IntBuffer;)V", (void *) android_glDeleteTextures__ILjava_nio_IntBuffer_2 },
+{"glDepthFunc", "(I)V", (void *) android_glDepthFunc__I },
+{"glDepthMask", "(Z)V", (void *) android_glDepthMask__Z },
+{"glDepthRangef", "(FF)V", (void *) android_glDepthRangef__FF },
+{"glDepthRangex", "(II)V", (void *) android_glDepthRangex__II },
+{"glDisable", "(I)V", (void *) android_glDisable__I },
+{"glDisableClientState", "(I)V", (void *) android_glDisableClientState__I },
+{"glDrawArrays", "(III)V", (void *) android_glDrawArrays__III },
+{"glDrawElements", "(IIILjava/nio/Buffer;)V", (void *) android_glDrawElements__IIILjava_nio_Buffer_2 },
+{"glEnable", "(I)V", (void *) android_glEnable__I },
+{"glEnableClientState", "(I)V", (void *) android_glEnableClientState__I },
+{"glFinish", "()V", (void *) android_glFinish__ },
+{"glFlush", "()V", (void *) android_glFlush__ },
+{"glFogf", "(IF)V", (void *) android_glFogf__IF },
+{"glFogfv", "(I[FI)V", (void *) android_glFogfv__I_3FI },
+{"glFogfv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glFogfv__ILjava_nio_FloatBuffer_2 },
+{"glFogx", "(II)V", (void *) android_glFogx__II },
+{"glFogxv", "(I[II)V", (void *) android_glFogxv__I_3II },
+{"glFogxv", "(ILjava/nio/IntBuffer;)V", (void *) android_glFogxv__ILjava_nio_IntBuffer_2 },
+{"glFrontFace", "(I)V", (void *) android_glFrontFace__I },
+{"glFrustumf", "(FFFFFF)V", (void *) android_glFrustumf__FFFFFF },
+{"glFrustumx", "(IIIIII)V", (void *) android_glFrustumx__IIIIII },
+{"glGenTextures", "(I[II)V", (void *) android_glGenTextures__I_3II },
+{"glGenTextures", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenTextures__ILjava_nio_IntBuffer_2 },
+{"glGetError", "()I", (void *) android_glGetError__ },
+{"glGetIntegerv", "(I[II)V", (void *) android_glGetIntegerv__I_3II },
+{"glGetIntegerv", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetIntegerv__ILjava_nio_IntBuffer_2 },
+{"glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString },
+{"glHint", "(II)V", (void *) android_glHint__II },
+{"glLightModelf", "(IF)V", (void *) android_glLightModelf__IF },
+{"glLightModelfv", "(I[FI)V", (void *) android_glLightModelfv__I_3FI },
+{"glLightModelfv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glLightModelfv__ILjava_nio_FloatBuffer_2 },
+{"glLightModelx", "(II)V", (void *) android_glLightModelx__II },
+{"glLightModelxv", "(I[II)V", (void *) android_glLightModelxv__I_3II },
+{"glLightModelxv", "(ILjava/nio/IntBuffer;)V", (void *) android_glLightModelxv__ILjava_nio_IntBuffer_2 },
+{"glLightf", "(IIF)V", (void *) android_glLightf__IIF },
+{"glLightfv", "(II[FI)V", (void *) android_glLightfv__II_3FI },
+{"glLightfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glLightfv__IILjava_nio_FloatBuffer_2 },
+{"glLightx", "(III)V", (void *) android_glLightx__III },
+{"glLightxv", "(II[II)V", (void *) android_glLightxv__II_3II },
+{"glLightxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glLightxv__IILjava_nio_IntBuffer_2 },
+{"glLineWidth", "(F)V", (void *) android_glLineWidth__F },
+{"glLineWidthx", "(I)V", (void *) android_glLineWidthx__I },
+{"glLoadIdentity", "()V", (void *) android_glLoadIdentity__ },
+{"glLoadMatrixf", "([FI)V", (void *) android_glLoadMatrixf___3FI },
+{"glLoadMatrixf", "(Ljava/nio/FloatBuffer;)V", (void *) android_glLoadMatrixf__Ljava_nio_FloatBuffer_2 },
+{"glLoadMatrixx", "([II)V", (void *) android_glLoadMatrixx___3II },
+{"glLoadMatrixx", "(Ljava/nio/IntBuffer;)V", (void *) android_glLoadMatrixx__Ljava_nio_IntBuffer_2 },
+{"glLogicOp", "(I)V", (void *) android_glLogicOp__I },
+{"glMaterialf", "(IIF)V", (void *) android_glMaterialf__IIF },
+{"glMaterialfv", "(II[FI)V", (void *) android_glMaterialfv__II_3FI },
+{"glMaterialfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glMaterialfv__IILjava_nio_FloatBuffer_2 },
+{"glMaterialx", "(III)V", (void *) android_glMaterialx__III },
+{"glMaterialxv", "(II[II)V", (void *) android_glMaterialxv__II_3II },
+{"glMaterialxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glMaterialxv__IILjava_nio_IntBuffer_2 },
+{"glMatrixMode", "(I)V", (void *) android_glMatrixMode__I },
+{"glMultMatrixf", "([FI)V", (void *) android_glMultMatrixf___3FI },
+{"glMultMatrixf", "(Ljava/nio/FloatBuffer;)V", (void *) android_glMultMatrixf__Ljava_nio_FloatBuffer_2 },
+{"glMultMatrixx", "([II)V", (void *) android_glMultMatrixx___3II },
+{"glMultMatrixx", "(Ljava/nio/IntBuffer;)V", (void *) android_glMultMatrixx__Ljava_nio_IntBuffer_2 },
+{"glMultiTexCoord4f", "(IFFFF)V", (void *) android_glMultiTexCoord4f__IFFFF },
+{"glMultiTexCoord4x", "(IIIII)V", (void *) android_glMultiTexCoord4x__IIIII },
+{"glNormal3f", "(FFF)V", (void *) android_glNormal3f__FFF },
+{"glNormal3x", "(III)V", (void *) android_glNormal3x__III },
+{"glNormalPointerBounds", "(IILjava/nio/Buffer;I)V", (void *) android_glNormalPointerBounds__IILjava_nio_Buffer_2I },
+{"glOrthof", "(FFFFFF)V", (void *) android_glOrthof__FFFFFF },
+{"glOrthox", "(IIIIII)V", (void *) android_glOrthox__IIIIII },
+{"glPixelStorei", "(II)V", (void *) android_glPixelStorei__II },
+{"glPointSize", "(F)V", (void *) android_glPointSize__F },
+{"glPointSizex", "(I)V", (void *) android_glPointSizex__I },
+{"glPolygonOffset", "(FF)V", (void *) android_glPolygonOffset__FF },
+{"glPolygonOffsetx", "(II)V", (void *) android_glPolygonOffsetx__II },
+{"glPopMatrix", "()V", (void *) android_glPopMatrix__ },
+{"glPushMatrix", "()V", (void *) android_glPushMatrix__ },
+{"glReadPixels", "(IIIIIILjava/nio/Buffer;)V", (void *) android_glReadPixels__IIIIIILjava_nio_Buffer_2 },
+{"glRotatef", "(FFFF)V", (void *) android_glRotatef__FFFF },
+{"glRotatex", "(IIII)V", (void *) android_glRotatex__IIII },
+{"glSampleCoverage", "(FZ)V", (void *) android_glSampleCoverage__FZ },
+{"glSampleCoveragex", "(IZ)V", (void *) android_glSampleCoveragex__IZ },
+{"glScalef", "(FFF)V", (void *) android_glScalef__FFF },
+{"glScalex", "(III)V", (void *) android_glScalex__III },
+{"glScissor", "(IIII)V", (void *) android_glScissor__IIII },
+{"glShadeModel", "(I)V", (void *) android_glShadeModel__I },
+{"glStencilFunc", "(III)V", (void *) android_glStencilFunc__III },
+{"glStencilMask", "(I)V", (void *) android_glStencilMask__I },
+{"glStencilOp", "(III)V", (void *) android_glStencilOp__III },
+{"glTexCoordPointerBounds", "(IIILjava/nio/Buffer;I)V", (void *) android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I },
+{"glTexEnvf", "(IIF)V", (void *) android_glTexEnvf__IIF },
+{"glTexEnvfv", "(II[FI)V", (void *) android_glTexEnvfv__II_3FI },
+{"glTexEnvfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glTexEnvfv__IILjava_nio_FloatBuffer_2 },
+{"glTexEnvx", "(III)V", (void *) android_glTexEnvx__III },
+{"glTexEnvxv", "(II[II)V", (void *) android_glTexEnvxv__II_3II },
+{"glTexEnvxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexEnvxv__IILjava_nio_IntBuffer_2 },
+{"glTexImage2D", "(IIIIIIIILjava/nio/Buffer;)V", (void *) android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2 },
+{"glTexParameterf", "(IIF)V", (void *) android_glTexParameterf__IIF },
+{"glTexParameterx", "(III)V", (void *) android_glTexParameterx__III },
+{"glTexSubImage2D", "(IIIIIIIILjava/nio/Buffer;)V", (void *) android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2 },
+{"glTranslatef", "(FFF)V", (void *) android_glTranslatef__FFF },
+{"glTranslatex", "(III)V", (void *) android_glTranslatex__III },
+{"glVertexPointerBounds", "(IIILjava/nio/Buffer;I)V", (void *) android_glVertexPointerBounds__IIILjava_nio_Buffer_2I },
+{"glViewport", "(IIII)V", (void *) android_glViewport__IIII },
+};
+
+int register_android_opengl_jni_GLES10(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
new file mode 100644
index 0000000..6114d6a
--- /dev/null
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -0,0 +1,254 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <GLES/gl.h>
+
+#include <private/opengles/gl_context.h>
+
+#define _NUM_COMPRESSED_TEXTURE_FORMATS \
+        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+
+static int initialized = 0;
+
+static jclass nioAccessClass;
+static jclass bufferClass;
+static jclass OOMEClass;
+static jclass UOEClass;
+static jclass IAEClass;
+static jclass AIOOBEClass;
+static jmethodID getBasePointerID;
+static jmethodID getBaseArrayID;
+static jmethodID getBaseArrayOffsetID;
+static jfieldID positionID;
+static jfieldID limitID;
+static jfieldID elementSizeShiftID;
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInitBuffer(JNIEnv *_env)
+{
+    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
+    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
+
+    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
+    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+
+    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
+            "getBasePointer", "(Ljava/nio/Buffer;)J");
+    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
+    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
+
+    positionID = _env->GetFieldID(bufferClass, "position", "I");
+    limitID = _env->GetFieldID(bufferClass, "limit", "I");
+    elementSizeShiftID =
+        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
+}
+
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    nativeClassInitBuffer(_env);
+
+    jclass IAEClassLocal =
+        _env->FindClass("java/lang/IllegalArgumentException");
+    jclass OOMEClassLocal =
+         _env->FindClass("java/lang/OutOfMemoryError");
+    jclass UOEClassLocal =
+         _env->FindClass("java/lang/UnsupportedOperationException");
+    jclass AIOOBEClassLocal =
+         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
+
+    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
+    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
+    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
+    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
+}
+
+static void *
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+{
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+    jint offset;
+    void *data;
+
+    position = _env->GetIntField(buffer, positionID);
+    limit = _env->GetIntField(buffer, limitID);
+    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    *remaining = (limit - position) << elementSizeShift;
+    pointer = _env->CallStaticLongMethod(nioAccessClass,
+            getBasePointerID, buffer);
+    if (pointer != 0L) {
+        *array = NULL;
+        return (void *) (jint) pointer;
+    }
+    
+    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
+            getBaseArrayID, buffer);
+    offset = _env->CallStaticIntMethod(nioAccessClass,
+            getBaseArrayOffsetID, buffer);
+    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
+    
+    return (void *) ((char *) data + offset);
+}
+
+
+static void
+releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
+{
+    _env->ReleasePrimitiveArrayCritical(array, data,
+					   commit ? 0 : JNI_ABORT);
+}
+
+// --------------------------------------------------------------------------
+
+/* GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) */
+static jint
+android_glQueryMatrixxOES___3II_3II
+  (JNIEnv *_env, jobject _this, jintArray mantissa_ref, jint mantissaOffset, jintArray exponent_ref, jint exponentOffset) {
+    jint _exception = 0;
+    GLbitfield _returnValue = -1;
+    GLfixed *mantissa_base = (GLfixed *) 0;
+    jint _mantissaRemaining;
+    GLfixed *mantissa = (GLfixed *) 0;
+    GLint *exponent_base = (GLint *) 0;
+    jint _exponentRemaining;
+    GLint *exponent = (GLint *) 0;
+
+    if (!mantissa_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "mantissa == null");
+        goto exit;
+    }
+    if (mantissaOffset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "mantissaOffset < 0");
+        goto exit;
+    }
+    _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
+    if (_mantissaRemaining < 16) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - mantissaOffset < 16");
+        goto exit;
+    }
+    mantissa_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(mantissa_ref, (jboolean *)0);
+    mantissa = mantissa_base + mantissaOffset;
+
+    if (!exponent_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "exponent == null");
+        goto exit;
+    }
+    if (exponentOffset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "exponentOffset < 0");
+        goto exit;
+    }
+    _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
+    if (_exponentRemaining < 16) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - exponentOffset < 16");
+        goto exit;
+    }
+    exponent_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(exponent_ref, (jboolean *)0);
+    exponent = exponent_base + exponentOffset;
+
+    _returnValue = glQueryMatrixxOES(
+        (GLfixed *)mantissa,
+        (GLint *)exponent
+    );
+
+exit:
+    if (exponent_base) {
+        _env->ReleasePrimitiveArrayCritical(exponent_ref, exponent_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (mantissa_base) {
+        _env->ReleasePrimitiveArrayCritical(mantissa_ref, mantissa_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    return _returnValue;
+}
+
+/* GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) */
+static jint
+android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jobject mantissa_buf, jobject exponent_buf) {
+    jint _exception = 0;
+    jarray _mantissaArray = (jarray) 0;
+    jarray _exponentArray = (jarray) 0;
+    GLbitfield _returnValue = -1;
+    jint _mantissaRemaining;
+    GLfixed *mantissa = (GLfixed *) 0;
+    jint _exponentRemaining;
+    GLint *exponent = (GLint *) 0;
+
+    mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining);
+    if (_mantissaRemaining < 16) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < 16");
+        goto exit;
+    }
+    exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining);
+    if (_exponentRemaining < 16) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < 16");
+        goto exit;
+    }
+    _returnValue = glQueryMatrixxOES(
+        (GLfixed *)mantissa,
+        (GLint *)exponent
+    );
+
+exit:
+    if (_mantissaArray) {
+        releasePointer(_env, _mantissaArray, exponent, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exponentArray) {
+        releasePointer(_env, _exponentArray, mantissa, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    return _returnValue;
+}
+
+static const char *classPathName = "android/opengl/GLES10Ext";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"glQueryMatrixxOES", "([II[II)I", (void *) android_glQueryMatrixxOES___3II_3II },
+{"glQueryMatrixxOES", "(Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;)I", (void *) android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
+};
+
+int register_android_opengl_jni_GLES10Ext(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
new file mode 100644
index 0000000..a7e59a8
--- /dev/null
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -0,0 +1,2469 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <GLES/gl.h>
+
+#include <private/opengles/gl_context.h>
+
+#define _NUM_COMPRESSED_TEXTURE_FORMATS \
+        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+
+static int initialized = 0;
+
+static jclass nioAccessClass;
+static jclass bufferClass;
+static jclass OOMEClass;
+static jclass UOEClass;
+static jclass IAEClass;
+static jclass AIOOBEClass;
+static jmethodID getBasePointerID;
+static jmethodID getBaseArrayID;
+static jmethodID getBaseArrayOffsetID;
+static jfieldID positionID;
+static jfieldID limitID;
+static jfieldID elementSizeShiftID;
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInitBuffer(JNIEnv *_env)
+{
+    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
+    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
+
+    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
+    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+
+    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
+            "getBasePointer", "(Ljava/nio/Buffer;)J");
+    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
+    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
+
+    positionID = _env->GetFieldID(bufferClass, "position", "I");
+    limitID = _env->GetFieldID(bufferClass, "limit", "I");
+    elementSizeShiftID =
+        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
+}
+
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    nativeClassInitBuffer(_env);
+
+    jclass IAEClassLocal =
+        _env->FindClass("java/lang/IllegalArgumentException");
+    jclass OOMEClassLocal =
+         _env->FindClass("java/lang/OutOfMemoryError");
+    jclass UOEClassLocal =
+         _env->FindClass("java/lang/UnsupportedOperationException");
+    jclass AIOOBEClassLocal =
+         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
+
+    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
+    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
+    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
+    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
+}
+
+static void *
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+{
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+    jint offset;
+    void *data;
+
+    position = _env->GetIntField(buffer, positionID);
+    limit = _env->GetIntField(buffer, limitID);
+    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    *remaining = (limit - position) << elementSizeShift;
+    pointer = _env->CallStaticLongMethod(nioAccessClass,
+            getBasePointerID, buffer);
+    if (pointer != 0L) {
+        *array = NULL;
+        return (void *) (jint) pointer;
+    }
+    
+    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
+            getBaseArrayID, buffer);
+    offset = _env->CallStaticIntMethod(nioAccessClass,
+            getBaseArrayOffsetID, buffer);
+    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
+    
+    return (void *) ((char *) data + offset);
+}
+
+
+static void
+releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
+{
+    _env->ReleasePrimitiveArrayCritical(array, data,
+					   commit ? 0 : JNI_ABORT);
+}
+
+// --------------------------------------------------------------------------
+
+/* void glBindBuffer ( GLenum target, GLuint buffer ) */
+static void
+android_glBindBuffer__II
+  (JNIEnv *_env, jobject _this, jint target, jint buffer) {
+    glBindBuffer(
+        (GLenum)target,
+        (GLuint)buffer
+    );
+}
+
+/* void glBufferData ( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage ) */
+static void
+android_glBufferData__IILjava_nio_Buffer_2I
+  (JNIEnv *_env, jobject _this, jint target, jint size, jobject data_buf, jint usage) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *data = (GLvoid *) 0;
+
+    if (data_buf) {
+        data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    }
+    glBufferData(
+        (GLenum)target,
+        (GLsizeiptr)size,
+        (GLvoid *)data,
+        (GLenum)usage
+    );
+    if (_array) {
+        releasePointer(_env, _array, data, JNI_FALSE);
+    }
+}
+
+/* void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data ) */
+static void
+android_glBufferSubData__IIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint offset, jint size, jobject data_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *data = (GLvoid *) 0;
+
+    data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
+    glBufferSubData(
+        (GLenum)target,
+        (GLintptr)offset,
+        (GLsizeiptr)size,
+        (GLvoid *)data
+    );
+    if (_array) {
+        releasePointer(_env, _array, data, JNI_FALSE);
+    }
+}
+
+/* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
+static void
+android_glClipPlanef__I_3FI
+  (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    GLfloat *equation_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *equation = (GLfloat *) 0;
+
+    if (!equation_ref) {
+        _env->ThrowNew(IAEClass, "equation == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(equation_ref) - offset;
+    equation_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(equation_ref, (jboolean *)0);
+    equation = equation_base + offset;
+
+    glClipPlanef(
+        (GLenum)plane,
+        (GLfloat *)equation
+    );
+
+exit:
+    if (equation_base) {
+        _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glClipPlanef ( GLenum plane, const GLfloat *equation ) */
+static void
+android_glClipPlanef__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *equation = (GLfloat *) 0;
+
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    glClipPlanef(
+        (GLenum)plane,
+        (GLfloat *)equation
+    );
+    if (_array) {
+        releasePointer(_env, _array, equation, JNI_FALSE);
+    }
+}
+
+/* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
+static void
+android_glClipPlanex__I_3II
+  (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    GLfixed *equation_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *equation = (GLfixed *) 0;
+
+    if (!equation_ref) {
+        _env->ThrowNew(IAEClass, "equation == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(equation_ref) - offset;
+    equation_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(equation_ref, (jboolean *)0);
+    equation = equation_base + offset;
+
+    glClipPlanex(
+        (GLenum)plane,
+        (GLfixed *)equation
+    );
+
+exit:
+    if (equation_base) {
+        _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glClipPlanex ( GLenum plane, const GLfixed *equation ) */
+static void
+android_glClipPlanex__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *equation = (GLfixed *) 0;
+
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    glClipPlanex(
+        (GLenum)plane,
+        (GLfixed *)equation
+    );
+    if (_array) {
+        releasePointer(_env, _array, equation, JNI_FALSE);
+    }
+}
+
+/* void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) */
+static void
+android_glColor4ub__BBBB
+  (JNIEnv *_env, jobject _this, jbyte red, jbyte green, jbyte blue, jbyte alpha) {
+    glColor4ub(
+        (GLubyte)red,
+        (GLubyte)green,
+        (GLubyte)blue,
+        (GLubyte)alpha
+    );
+}
+
+/* void glColorPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
+static void
+android_glColorPointer__IIII
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jint offset) {
+    glColorPointer(
+        (GLint)size,
+        (GLenum)type,
+        (GLsizei)stride,
+        (const GLvoid *)offset
+    );
+}
+
+/* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
+static void
+android_glDeleteBuffers__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    GLuint *buffers_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *buffers = (GLuint *) 0;
+
+    if (!buffers_ref) {
+        _env->ThrowNew(IAEClass, "buffers == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(buffers_ref) - offset;
+    if (_remaining < n) {
+        _env->ThrowNew(IAEClass, "length - offset < n");
+        goto exit;
+    }
+    buffers_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(buffers_ref, (jboolean *)0);
+    buffers = buffers_base + offset;
+
+    glDeleteBuffers(
+        (GLsizei)n,
+        (GLuint *)buffers
+    );
+
+exit:
+    if (buffers_base) {
+        _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glDeleteBuffers ( GLsizei n, const GLuint *buffers ) */
+static void
+android_glDeleteBuffers__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLuint *buffers = (GLuint *) 0;
+
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    if (_remaining < n) {
+        _env->ThrowNew(IAEClass, "remaining() < n");
+        goto exit;
+    }
+    glDeleteBuffers(
+        (GLsizei)n,
+        (GLuint *)buffers
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, buffers, JNI_FALSE);
+    }
+}
+
+/* void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset ) */
+static void
+android_glDrawElements__IIII
+  (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint offset) {
+    glDrawElements(
+        (GLenum)mode,
+        (GLsizei)count,
+        (GLenum)type,
+        (const GLvoid *)offset
+    );
+}
+
+/* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
+static void
+android_glGenBuffers__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray buffers_ref, jint offset) {
+    jint _exception = 0;
+    GLuint *buffers_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *buffers = (GLuint *) 0;
+
+    if (!buffers_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "buffers == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(buffers_ref) - offset;
+    if (_remaining < n) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < n");
+        goto exit;
+    }
+    buffers_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(buffers_ref, (jboolean *)0);
+    buffers = buffers_base + offset;
+
+    glGenBuffers(
+        (GLsizei)n,
+        (GLuint *)buffers
+    );
+
+exit:
+    if (buffers_base) {
+        _env->ReleasePrimitiveArrayCritical(buffers_ref, buffers_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGenBuffers ( GLsizei n, GLuint *buffers ) */
+static void
+android_glGenBuffers__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject buffers_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLuint *buffers = (GLuint *) 0;
+
+    buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
+    if (_remaining < n) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < n");
+        goto exit;
+    }
+    glGenBuffers(
+        (GLsizei)n,
+        (GLuint *)buffers
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, buffers, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
+static void
+android_glGetBooleanv__I_3ZI
+  (JNIEnv *_env, jobject _this, jint pname, jbooleanArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLboolean *params_base = (GLboolean *) 0;
+    jint _remaining;
+    GLboolean *params = (GLboolean *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLboolean *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetBooleanv(
+        (GLenum)pname,
+        (GLboolean *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetBooleanv ( GLenum pname, GLboolean *params ) */
+static void
+android_glGetBooleanv__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLboolean *params = (GLboolean *) 0;
+
+    params = (GLboolean *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetBooleanv(
+        (GLenum)pname,
+        (GLboolean *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetBufferParameteriv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    _env->ThrowNew(UOEClass,
+        "glGetBufferParameteriv");
+}
+
+/* void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    _env->ThrowNew(UOEClass,
+        "glGetBufferParameteriv");
+}
+
+/* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
+static void
+android_glGetClipPlanef__I_3FI
+  (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *eqn_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *eqn = (GLfloat *) 0;
+
+    if (!eqn_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "eqn == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(eqn_ref) - offset;
+    eqn_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(eqn_ref, (jboolean *)0);
+    eqn = eqn_base + offset;
+
+    glGetClipPlanef(
+        (GLenum)pname,
+        (GLfloat *)eqn
+    );
+
+exit:
+    if (eqn_base) {
+        _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetClipPlanef ( GLenum pname, GLfloat *eqn ) */
+static void
+android_glGetClipPlanef__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *eqn = (GLfloat *) 0;
+
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    glGetClipPlanef(
+        (GLenum)pname,
+        (GLfloat *)eqn
+    );
+    if (_array) {
+        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) */
+static void
+android_glGetClipPlanex__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *eqn_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *eqn = (GLfixed *) 0;
+
+    if (!eqn_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "eqn == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(eqn_ref) - offset;
+    eqn_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(eqn_ref, (jboolean *)0);
+    eqn = eqn_base + offset;
+
+    glGetClipPlanex(
+        (GLenum)pname,
+        (GLfixed *)eqn
+    );
+
+exit:
+    if (eqn_base) {
+        _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetClipPlanex ( GLenum pname, GLfixed *eqn ) */
+static void
+android_glGetClipPlanex__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *eqn = (GLfixed *) 0;
+
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    glGetClipPlanex(
+        (GLenum)pname,
+        (GLfixed *)eqn
+    );
+    if (_array) {
+        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetFixedv ( GLenum pname, GLfixed *params ) */
+static void
+android_glGetFixedv__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetFixedv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetFixedv ( GLenum pname, GLfixed *params ) */
+static void
+android_glGetFixedv__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetFixedv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetFloatv ( GLenum pname, GLfloat *params ) */
+static void
+android_glGetFloatv__I_3FI
+  (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetFloatv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetFloatv ( GLenum pname, GLfloat *params ) */
+static void
+android_glGetFloatv__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetFloatv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) */
+static void
+android_glGetLightfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetLightfv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params ) */
+static void
+android_glGetLightfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetLightfv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
+static void
+android_glGetLightxv__II_3II
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetLightxv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params ) */
+static void
+android_glGetLightxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SPOT_EXPONENT)
+        case GL_SPOT_EXPONENT:
+#endif // defined(GL_SPOT_EXPONENT)
+#if defined(GL_SPOT_CUTOFF)
+        case GL_SPOT_CUTOFF:
+#endif // defined(GL_SPOT_CUTOFF)
+#if defined(GL_CONSTANT_ATTENUATION)
+        case GL_CONSTANT_ATTENUATION:
+#endif // defined(GL_CONSTANT_ATTENUATION)
+#if defined(GL_LINEAR_ATTENUATION)
+        case GL_LINEAR_ATTENUATION:
+#endif // defined(GL_LINEAR_ATTENUATION)
+#if defined(GL_QUADRATIC_ATTENUATION)
+        case GL_QUADRATIC_ATTENUATION:
+#endif // defined(GL_QUADRATIC_ATTENUATION)
+            _needed = 1;
+            break;
+#if defined(GL_SPOT_DIRECTION)
+        case GL_SPOT_DIRECTION:
+#endif // defined(GL_SPOT_DIRECTION)
+            _needed = 3;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetLightxv(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
+static void
+android_glGetMaterialfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetMaterialfv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params ) */
+static void
+android_glGetMaterialfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetMaterialfv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
+static void
+android_glGetMaterialxv__II_3II
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetMaterialxv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params ) */
+static void
+android_glGetMaterialxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_SHININESS)
+        case GL_SHININESS:
+#endif // defined(GL_SHININESS)
+            _needed = 1;
+            break;
+#if defined(GL_AMBIENT)
+        case GL_AMBIENT:
+#endif // defined(GL_AMBIENT)
+#if defined(GL_DIFFUSE)
+        case GL_DIFFUSE:
+#endif // defined(GL_DIFFUSE)
+#if defined(GL_SPECULAR)
+        case GL_SPECULAR:
+#endif // defined(GL_SPECULAR)
+#if defined(GL_EMISSION)
+        case GL_EMISSION:
+#endif // defined(GL_EMISSION)
+#if defined(GL_AMBIENT_AND_DIFFUSE)
+        case GL_AMBIENT_AND_DIFFUSE:
+#endif // defined(GL_AMBIENT_AND_DIFFUSE)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetMaterialxv(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexEnvfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexEnvfv(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexEnvfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetTexEnvfv(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
+static void
+android_glGetTexEnviv__II_3II
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexEnviv(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params ) */
+static void
+android_glGetTexEnviv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetTexEnviv(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexEnvxv__II_3II
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexEnvxv(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexEnvxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glGetTexEnvxv(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexParameterfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexParameterfv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glGetTexParameterfv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetTexParameteriv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexParameteriv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetTexParameteriv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glGetTexParameteriv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexParameterxv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexParameterxv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexParameterxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glGetTexParameterxv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* GLboolean glIsBuffer ( GLuint buffer ) */
+static jboolean
+android_glIsBuffer__I
+  (JNIEnv *_env, jobject _this, jint buffer) {
+    GLboolean _returnValue;
+    _returnValue = glIsBuffer(
+        (GLuint)buffer
+    );
+    return _returnValue;
+}
+
+/* GLboolean glIsEnabled ( GLenum cap ) */
+static jboolean
+android_glIsEnabled__I
+  (JNIEnv *_env, jobject _this, jint cap) {
+    GLboolean _returnValue;
+    _returnValue = glIsEnabled(
+        (GLenum)cap
+    );
+    return _returnValue;
+}
+
+/* GLboolean glIsTexture ( GLuint texture ) */
+static jboolean
+android_glIsTexture__I
+  (JNIEnv *_env, jobject _this, jint texture) {
+    GLboolean _returnValue;
+    _returnValue = glIsTexture(
+        (GLuint)texture
+    );
+    return _returnValue;
+}
+
+/* void glNormalPointer ( GLenum type, GLsizei stride, GLint offset ) */
+static void
+android_glNormalPointer__III
+  (JNIEnv *_env, jobject _this, jint type, jint stride, jint offset) {
+    glNormalPointer(
+        (GLenum)type,
+        (GLsizei)stride,
+        (const GLvoid *)offset
+    );
+}
+
+/* void glPointParameterf ( GLenum pname, GLfloat param ) */
+static void
+android_glPointParameterf__IF
+  (JNIEnv *_env, jobject _this, jint pname, jfloat param) {
+    glPointParameterf(
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glPointParameterfv ( GLenum pname, const GLfloat *params ) */
+static void
+android_glPointParameterfv__I_3FI
+  (JNIEnv *_env, jobject _this, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glPointParameterfv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glPointParameterfv ( GLenum pname, const GLfloat *params ) */
+static void
+android_glPointParameterfv__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glPointParameterfv(
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glPointParameterx ( GLenum pname, GLfixed param ) */
+static void
+android_glPointParameterx__II
+  (JNIEnv *_env, jobject _this, jint pname, jint param) {
+    glPointParameterx(
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glPointParameterxv ( GLenum pname, const GLfixed *params ) */
+static void
+android_glPointParameterxv__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glPointParameterxv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glPointParameterxv ( GLenum pname, const GLfixed *params ) */
+static void
+android_glPointParameterxv__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glPointParameterxv(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer ) */
+static void
+android_glPointSizePointerOES__IILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint type, jint stride, jobject pointer_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLvoid *pointer = (GLvoid *) 0;
+
+    pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining);
+    glPointSizePointerOES(
+        (GLenum)type,
+        (GLsizei)stride,
+        (GLvoid *)pointer
+    );
+    if (_array) {
+        releasePointer(_env, _array, pointer, JNI_FALSE);
+    }
+}
+
+/* void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
+static void
+android_glTexCoordPointer__IIII
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jint offset) {
+    glTexCoordPointer(
+        (GLint)size,
+        (GLenum)type,
+        (GLsizei)stride,
+        (const GLvoid *)offset
+    );
+}
+
+/* void glTexEnvi ( GLenum target, GLenum pname, GLint param ) */
+static void
+android_glTexEnvi__III
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) {
+    glTexEnvi(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint)param
+    );
+}
+
+/* void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) */
+static void
+android_glTexEnviv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "length - offset < needed");
+        goto exit;
+    }
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexEnviv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexEnviv ( GLenum target, GLenum pname, const GLint *params ) */
+static void
+android_glTexEnviv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    int _needed;
+    switch (pname) {
+#if defined(GL_TEXTURE_ENV_MODE)
+        case GL_TEXTURE_ENV_MODE:
+#endif // defined(GL_TEXTURE_ENV_MODE)
+#if defined(GL_COMBINE_RGB)
+        case GL_COMBINE_RGB:
+#endif // defined(GL_COMBINE_RGB)
+#if defined(GL_COMBINE_ALPHA)
+        case GL_COMBINE_ALPHA:
+#endif // defined(GL_COMBINE_ALPHA)
+            _needed = 1;
+            break;
+#if defined(GL_TEXTURE_ENV_COLOR)
+        case GL_TEXTURE_ENV_COLOR:
+#endif // defined(GL_TEXTURE_ENV_COLOR)
+            _needed = 4;
+            break;
+        default:
+            _needed = 0;
+            break;
+    }
+    if (_remaining < _needed) {
+        _env->ThrowNew(IAEClass, "remaining() < needed");
+        goto exit;
+    }
+    glTexEnviv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
+static void
+android_glTexParameterfv__II_3FI
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexParameterfv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params ) */
+static void
+android_glTexParameterfv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glTexParameterfv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexParameteri ( GLenum target, GLenum pname, GLint param ) */
+static void
+android_glTexParameteri__III
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) {
+    glTexParameteri(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint)param
+    );
+}
+
+/* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
+static void
+android_glTexParameteriv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexParameteriv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params ) */
+static void
+android_glTexParameteriv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glTexParameteriv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexParameterxv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "length - offset < 1");
+        goto exit;
+    }
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexParameterxv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexParameterxv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    if (_remaining < 1) {
+        _env->ThrowNew(IAEClass, "remaining() < 1");
+        goto exit;
+    }
+    glTexParameterxv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset ) */
+static void
+android_glVertexPointer__IIII
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jint offset) {
+    glVertexPointer(
+        (GLint)size,
+        (GLenum)type,
+        (GLsizei)stride,
+        (const GLvoid *)offset
+    );
+}
+
+static const char *classPathName = "android/opengl/GLES11";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"glBindBuffer", "(II)V", (void *) android_glBindBuffer__II },
+{"glBufferData", "(IILjava/nio/Buffer;I)V", (void *) android_glBufferData__IILjava_nio_Buffer_2I },
+{"glBufferSubData", "(IIILjava/nio/Buffer;)V", (void *) android_glBufferSubData__IIILjava_nio_Buffer_2 },
+{"glClipPlanef", "(I[FI)V", (void *) android_glClipPlanef__I_3FI },
+{"glClipPlanef", "(ILjava/nio/FloatBuffer;)V", (void *) android_glClipPlanef__ILjava_nio_FloatBuffer_2 },
+{"glClipPlanex", "(I[II)V", (void *) android_glClipPlanex__I_3II },
+{"glClipPlanex", "(ILjava/nio/IntBuffer;)V", (void *) android_glClipPlanex__ILjava_nio_IntBuffer_2 },
+{"glColor4ub", "(BBBB)V", (void *) android_glColor4ub__BBBB },
+{"glColorPointer", "(IIII)V", (void *) android_glColorPointer__IIII },
+{"glDeleteBuffers", "(I[II)V", (void *) android_glDeleteBuffers__I_3II },
+{"glDeleteBuffers", "(ILjava/nio/IntBuffer;)V", (void *) android_glDeleteBuffers__ILjava_nio_IntBuffer_2 },
+{"glDrawElements", "(IIII)V", (void *) android_glDrawElements__IIII },
+{"glGenBuffers", "(I[II)V", (void *) android_glGenBuffers__I_3II },
+{"glGenBuffers", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenBuffers__ILjava_nio_IntBuffer_2 },
+{"glGetBooleanv", "(I[ZI)V", (void *) android_glGetBooleanv__I_3ZI },
+{"glGetBooleanv", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetBooleanv__ILjava_nio_IntBuffer_2 },
+{"glGetBufferParameteriv", "(II[II)V", (void *) android_glGetBufferParameteriv__II_3II },
+{"glGetBufferParameteriv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2 },
+{"glGetClipPlanef", "(I[FI)V", (void *) android_glGetClipPlanef__I_3FI },
+{"glGetClipPlanef", "(ILjava/nio/FloatBuffer;)V", (void *) android_glGetClipPlanef__ILjava_nio_FloatBuffer_2 },
+{"glGetClipPlanex", "(I[II)V", (void *) android_glGetClipPlanex__I_3II },
+{"glGetClipPlanex", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetClipPlanex__ILjava_nio_IntBuffer_2 },
+{"glGetFixedv", "(I[II)V", (void *) android_glGetFixedv__I_3II },
+{"glGetFixedv", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetFixedv__ILjava_nio_IntBuffer_2 },
+{"glGetFloatv", "(I[FI)V", (void *) android_glGetFloatv__I_3FI },
+{"glGetFloatv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glGetFloatv__ILjava_nio_FloatBuffer_2 },
+{"glGetLightfv", "(II[FI)V", (void *) android_glGetLightfv__II_3FI },
+{"glGetLightfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetLightfv__IILjava_nio_FloatBuffer_2 },
+{"glGetLightxv", "(II[II)V", (void *) android_glGetLightxv__II_3II },
+{"glGetLightxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetLightxv__IILjava_nio_IntBuffer_2 },
+{"glGetMaterialfv", "(II[FI)V", (void *) android_glGetMaterialfv__II_3FI },
+{"glGetMaterialfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetMaterialfv__IILjava_nio_FloatBuffer_2 },
+{"glGetMaterialxv", "(II[II)V", (void *) android_glGetMaterialxv__II_3II },
+{"glGetMaterialxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetMaterialxv__IILjava_nio_IntBuffer_2 },
+{"glGetTexEnvfv", "(II[FI)V", (void *) android_glGetTexEnvfv__II_3FI },
+{"glGetTexEnvfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetTexEnvfv__IILjava_nio_FloatBuffer_2 },
+{"glGetTexEnviv", "(II[II)V", (void *) android_glGetTexEnviv__II_3II },
+{"glGetTexEnviv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexEnviv__IILjava_nio_IntBuffer_2 },
+{"glGetTexEnvxv", "(II[II)V", (void *) android_glGetTexEnvxv__II_3II },
+{"glGetTexEnvxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexEnvxv__IILjava_nio_IntBuffer_2 },
+{"glGetTexParameterfv", "(II[FI)V", (void *) android_glGetTexParameterfv__II_3FI },
+{"glGetTexParameterfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetTexParameterfv__IILjava_nio_FloatBuffer_2 },
+{"glGetTexParameteriv", "(II[II)V", (void *) android_glGetTexParameteriv__II_3II },
+{"glGetTexParameteriv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexParameteriv__IILjava_nio_IntBuffer_2 },
+{"glGetTexParameterxv", "(II[II)V", (void *) android_glGetTexParameterxv__II_3II },
+{"glGetTexParameterxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexParameterxv__IILjava_nio_IntBuffer_2 },
+{"glIsBuffer", "(I)Z", (void *) android_glIsBuffer__I },
+{"glIsEnabled", "(I)Z", (void *) android_glIsEnabled__I },
+{"glIsTexture", "(I)Z", (void *) android_glIsTexture__I },
+{"glNormalPointer", "(III)V", (void *) android_glNormalPointer__III },
+{"glPointParameterf", "(IF)V", (void *) android_glPointParameterf__IF },
+{"glPointParameterfv", "(I[FI)V", (void *) android_glPointParameterfv__I_3FI },
+{"glPointParameterfv", "(ILjava/nio/FloatBuffer;)V", (void *) android_glPointParameterfv__ILjava_nio_FloatBuffer_2 },
+{"glPointParameterx", "(II)V", (void *) android_glPointParameterx__II },
+{"glPointParameterxv", "(I[II)V", (void *) android_glPointParameterxv__I_3II },
+{"glPointParameterxv", "(ILjava/nio/IntBuffer;)V", (void *) android_glPointParameterxv__ILjava_nio_IntBuffer_2 },
+{"glPointSizePointerOES", "(IILjava/nio/Buffer;)V", (void *) android_glPointSizePointerOES__IILjava_nio_Buffer_2 },
+{"glTexCoordPointer", "(IIII)V", (void *) android_glTexCoordPointer__IIII },
+{"glTexEnvi", "(III)V", (void *) android_glTexEnvi__III },
+{"glTexEnviv", "(II[II)V", (void *) android_glTexEnviv__II_3II },
+{"glTexEnviv", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexEnviv__IILjava_nio_IntBuffer_2 },
+{"glTexParameterfv", "(II[FI)V", (void *) android_glTexParameterfv__II_3FI },
+{"glTexParameterfv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glTexParameterfv__IILjava_nio_FloatBuffer_2 },
+{"glTexParameteri", "(III)V", (void *) android_glTexParameteri__III },
+{"glTexParameteriv", "(II[II)V", (void *) android_glTexParameteriv__II_3II },
+{"glTexParameteriv", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexParameteriv__IILjava_nio_IntBuffer_2 },
+{"glTexParameterxv", "(II[II)V", (void *) android_glTexParameterxv__II_3II },
+{"glTexParameterxv", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexParameterxv__IILjava_nio_IntBuffer_2 },
+{"glVertexPointer", "(IIII)V", (void *) android_glVertexPointer__IIII },
+};
+
+int register_android_opengl_jni_GLES11(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
new file mode 100644
index 0000000..069cec1
--- /dev/null
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -0,0 +1,2465 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <GLES/gl.h>
+
+#include <private/opengles/gl_context.h>
+
+#define _NUM_COMPRESSED_TEXTURE_FORMATS \
+        (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS)
+
+static int initialized = 0;
+
+static jclass nioAccessClass;
+static jclass bufferClass;
+static jclass OOMEClass;
+static jclass UOEClass;
+static jclass IAEClass;
+static jclass AIOOBEClass;
+static jmethodID getBasePointerID;
+static jmethodID getBaseArrayID;
+static jmethodID getBaseArrayOffsetID;
+static jfieldID positionID;
+static jfieldID limitID;
+static jfieldID elementSizeShiftID;
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInitBuffer(JNIEnv *_env)
+{
+    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
+    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
+
+    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
+    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+
+    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
+            "getBasePointer", "(Ljava/nio/Buffer;)J");
+    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
+    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
+
+    positionID = _env->GetFieldID(bufferClass, "position", "I");
+    limitID = _env->GetFieldID(bufferClass, "limit", "I");
+    elementSizeShiftID =
+        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
+}
+
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    nativeClassInitBuffer(_env);
+
+    jclass IAEClassLocal =
+        _env->FindClass("java/lang/IllegalArgumentException");
+    jclass OOMEClassLocal =
+         _env->FindClass("java/lang/OutOfMemoryError");
+    jclass UOEClassLocal =
+         _env->FindClass("java/lang/UnsupportedOperationException");
+    jclass AIOOBEClassLocal =
+         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
+
+    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
+    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
+    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
+    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
+}
+
+static void *
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
+{
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+    jint offset;
+    void *data;
+
+    position = _env->GetIntField(buffer, positionID);
+    limit = _env->GetIntField(buffer, limitID);
+    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    *remaining = (limit - position) << elementSizeShift;
+    pointer = _env->CallStaticLongMethod(nioAccessClass,
+            getBasePointerID, buffer);
+    if (pointer != 0L) {
+        *array = NULL;
+        return (void *) (jint) pointer;
+    }
+    
+    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
+            getBaseArrayID, buffer);
+    offset = _env->CallStaticIntMethod(nioAccessClass,
+            getBaseArrayOffsetID, buffer);
+    data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
+    
+    return (void *) ((char *) data + offset);
+}
+
+
+static void
+releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
+{
+    _env->ReleasePrimitiveArrayCritical(array, data,
+					   commit ? 0 : JNI_ABORT);
+}
+
+// --------------------------------------------------------------------------
+
+/* void glBlendEquationSeparateOES ( GLenum modeRGB, GLenum modeAlpha ) */
+static void
+android_glBlendEquationSeparateOES__II
+  (JNIEnv *_env, jobject _this, jint modeRGB, jint modeAlpha) {
+    glBlendEquationSeparateOES(
+        (GLenum)modeRGB,
+        (GLenum)modeAlpha
+    );
+}
+
+/* void glBlendFuncSeparateOES ( GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha ) */
+static void
+android_glBlendFuncSeparateOES__IIII
+  (JNIEnv *_env, jobject _this, jint srcRGB, jint dstRGB, jint srcAlpha, jint dstAlpha) {
+    glBlendFuncSeparateOES(
+        (GLenum)srcRGB,
+        (GLenum)dstRGB,
+        (GLenum)srcAlpha,
+        (GLenum)dstAlpha
+    );
+}
+
+/* void glBlendEquationOES ( GLenum mode ) */
+static void
+android_glBlendEquationOES__I
+  (JNIEnv *_env, jobject _this, jint mode) {
+    glBlendEquationOES(
+        (GLenum)mode
+    );
+}
+
+/* void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height ) */
+static void
+android_glDrawTexsOES__SSSSS
+  (JNIEnv *_env, jobject _this, jshort x, jshort y, jshort z, jshort width, jshort height) {
+    glDrawTexsOES(
+        (GLshort)x,
+        (GLshort)y,
+        (GLshort)z,
+        (GLshort)width,
+        (GLshort)height
+    );
+}
+
+/* void glDrawTexiOES ( GLint x, GLint y, GLint z, GLint width, GLint height ) */
+static void
+android_glDrawTexiOES__IIIII
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint z, jint width, jint height) {
+    glDrawTexiOES(
+        (GLint)x,
+        (GLint)y,
+        (GLint)z,
+        (GLint)width,
+        (GLint)height
+    );
+}
+
+/* void glDrawTexxOES ( GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height ) */
+static void
+android_glDrawTexxOES__IIIII
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint z, jint width, jint height) {
+    glDrawTexxOES(
+        (GLfixed)x,
+        (GLfixed)y,
+        (GLfixed)z,
+        (GLfixed)width,
+        (GLfixed)height
+    );
+}
+
+/* void glDrawTexsvOES ( const GLshort *coords ) */
+static void
+android_glDrawTexsvOES___3SI
+  (JNIEnv *_env, jobject _this, jshortArray coords_ref, jint offset) {
+    GLshort *coords_base = (GLshort *) 0;
+    jint _remaining;
+    GLshort *coords = (GLshort *) 0;
+
+    if (!coords_ref) {
+        _env->ThrowNew(IAEClass, "coords == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(coords_ref) - offset;
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "length - offset < 5");
+        goto exit;
+    }
+    coords_base = (GLshort *)
+        _env->GetPrimitiveArrayCritical(coords_ref, (jboolean *)0);
+    coords = coords_base + offset;
+
+    glDrawTexsvOES(
+        (GLshort *)coords
+    );
+
+exit:
+    if (coords_base) {
+        _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glDrawTexsvOES ( const GLshort *coords ) */
+static void
+android_glDrawTexsvOES__Ljava_nio_ShortBuffer_2
+  (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLshort *coords = (GLshort *) 0;
+
+    coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining);
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "remaining() < 5");
+        goto exit;
+    }
+    glDrawTexsvOES(
+        (GLshort *)coords
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, coords, JNI_FALSE);
+    }
+}
+
+/* void glDrawTexivOES ( const GLint *coords ) */
+static void
+android_glDrawTexivOES___3II
+  (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    GLint *coords_base = (GLint *) 0;
+    jint _remaining;
+    GLint *coords = (GLint *) 0;
+
+    if (!coords_ref) {
+        _env->ThrowNew(IAEClass, "coords == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(coords_ref) - offset;
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "length - offset < 5");
+        goto exit;
+    }
+    coords_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(coords_ref, (jboolean *)0);
+    coords = coords_base + offset;
+
+    glDrawTexivOES(
+        (GLint *)coords
+    );
+
+exit:
+    if (coords_base) {
+        _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glDrawTexivOES ( const GLint *coords ) */
+static void
+android_glDrawTexivOES__Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *coords = (GLint *) 0;
+
+    coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining);
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "remaining() < 5");
+        goto exit;
+    }
+    glDrawTexivOES(
+        (GLint *)coords
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, coords, JNI_FALSE);
+    }
+}
+
+/* void glDrawTexxvOES ( const GLfixed *coords ) */
+static void
+android_glDrawTexxvOES___3II
+  (JNIEnv *_env, jobject _this, jintArray coords_ref, jint offset) {
+    GLfixed *coords_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *coords = (GLfixed *) 0;
+
+    if (!coords_ref) {
+        _env->ThrowNew(IAEClass, "coords == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(coords_ref) - offset;
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "length - offset < 5");
+        goto exit;
+    }
+    coords_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(coords_ref, (jboolean *)0);
+    coords = coords_base + offset;
+
+    glDrawTexxvOES(
+        (GLfixed *)coords
+    );
+
+exit:
+    if (coords_base) {
+        _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glDrawTexxvOES ( const GLfixed *coords ) */
+static void
+android_glDrawTexxvOES__Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *coords = (GLfixed *) 0;
+
+    coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining);
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "remaining() < 5");
+        goto exit;
+    }
+    glDrawTexxvOES(
+        (GLfixed *)coords
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, coords, JNI_FALSE);
+    }
+}
+
+/* void glDrawTexfOES ( GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height ) */
+static void
+android_glDrawTexfOES__FFFFF
+  (JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z, jfloat width, jfloat height) {
+    glDrawTexfOES(
+        (GLfloat)x,
+        (GLfloat)y,
+        (GLfloat)z,
+        (GLfloat)width,
+        (GLfloat)height
+    );
+}
+
+/* void glDrawTexfvOES ( const GLfloat *coords ) */
+static void
+android_glDrawTexfvOES___3FI
+  (JNIEnv *_env, jobject _this, jfloatArray coords_ref, jint offset) {
+    GLfloat *coords_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *coords = (GLfloat *) 0;
+
+    if (!coords_ref) {
+        _env->ThrowNew(IAEClass, "coords == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(coords_ref) - offset;
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "length - offset < 5");
+        goto exit;
+    }
+    coords_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(coords_ref, (jboolean *)0);
+    coords = coords_base + offset;
+
+    glDrawTexfvOES(
+        (GLfloat *)coords
+    );
+
+exit:
+    if (coords_base) {
+        _env->ReleasePrimitiveArrayCritical(coords_ref, coords_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glDrawTexfvOES ( const GLfloat *coords ) */
+static void
+android_glDrawTexfvOES__Ljava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jobject coords_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *coords = (GLfloat *) 0;
+
+    coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining);
+    if (_remaining < 5) {
+        _env->ThrowNew(IAEClass, "remaining() < 5");
+        goto exit;
+    }
+    glDrawTexfvOES(
+        (GLfloat *)coords
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, coords, JNI_FALSE);
+    }
+}
+
+/* void glEGLImageTargetTexture2DOES ( GLenum target, GLeglImageOES image ) */
+static void
+android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLeglImageOES image = (GLeglImageOES) 0;
+
+    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining);
+    glEGLImageTargetTexture2DOES(
+        (GLenum)target,
+        (GLeglImageOES)image
+    );
+    if (_array) {
+        releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glEGLImageTargetRenderbufferStorageOES ( GLenum target, GLeglImageOES image ) */
+static void
+android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint target, jobject image_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLeglImageOES image = (GLeglImageOES) 0;
+
+    image = (GLeglImageOES)getPointer(_env, image_buf, &_array, &_remaining);
+    glEGLImageTargetRenderbufferStorageOES(
+        (GLenum)target,
+        (GLeglImageOES)image
+    );
+    if (_array) {
+        releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glAlphaFuncxOES ( GLenum func, GLclampx ref ) */
+static void
+android_glAlphaFuncxOES__II
+  (JNIEnv *_env, jobject _this, jint func, jint ref) {
+    glAlphaFuncxOES(
+        (GLenum)func,
+        (GLclampx)ref
+    );
+}
+
+/* void glClearColorxOES ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha ) */
+static void
+android_glClearColorxOES__IIII
+  (JNIEnv *_env, jobject _this, jint red, jint green, jint blue, jint alpha) {
+    glClearColorxOES(
+        (GLclampx)red,
+        (GLclampx)green,
+        (GLclampx)blue,
+        (GLclampx)alpha
+    );
+}
+
+/* void glClearDepthxOES ( GLclampx depth ) */
+static void
+android_glClearDepthxOES__I
+  (JNIEnv *_env, jobject _this, jint depth) {
+    glClearDepthxOES(
+        (GLclampx)depth
+    );
+}
+
+/* void glClipPlanexOES ( GLenum plane, const GLfixed *equation ) */
+static void
+android_glClipPlanexOES__I_3II
+  (JNIEnv *_env, jobject _this, jint plane, jintArray equation_ref, jint offset) {
+    GLfixed *equation_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *equation = (GLfixed *) 0;
+
+    if (!equation_ref) {
+        _env->ThrowNew(IAEClass, "equation == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(equation_ref) - offset;
+    equation_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(equation_ref, (jboolean *)0);
+    equation = equation_base + offset;
+
+    glClipPlanexOES(
+        (GLenum)plane,
+        (GLfixed *)equation
+    );
+
+exit:
+    if (equation_base) {
+        _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glClipPlanexOES ( GLenum plane, const GLfixed *equation ) */
+static void
+android_glClipPlanexOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *equation = (GLfixed *) 0;
+
+    equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
+    glClipPlanexOES(
+        (GLenum)plane,
+        (GLfixed *)equation
+    );
+    if (_array) {
+        releasePointer(_env, _array, equation, JNI_FALSE);
+    }
+}
+
+/* void glColor4xOES ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha ) */
+static void
+android_glColor4xOES__IIII
+  (JNIEnv *_env, jobject _this, jint red, jint green, jint blue, jint alpha) {
+    glColor4xOES(
+        (GLfixed)red,
+        (GLfixed)green,
+        (GLfixed)blue,
+        (GLfixed)alpha
+    );
+}
+
+/* void glDepthRangexOES ( GLclampx zNear, GLclampx zFar ) */
+static void
+android_glDepthRangexOES__II
+  (JNIEnv *_env, jobject _this, jint zNear, jint zFar) {
+    glDepthRangexOES(
+        (GLclampx)zNear,
+        (GLclampx)zFar
+    );
+}
+
+/* void glFogxOES ( GLenum pname, GLfixed param ) */
+static void
+android_glFogxOES__II
+  (JNIEnv *_env, jobject _this, jint pname, jint param) {
+    glFogxOES(
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glFogxvOES ( GLenum pname, const GLfixed *params ) */
+static void
+android_glFogxvOES__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glFogxvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glFogxvOES ( GLenum pname, const GLfixed *params ) */
+static void
+android_glFogxvOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glFogxvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glFrustumxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */
+static void
+android_glFrustumxOES__IIIIII
+  (JNIEnv *_env, jobject _this, jint left, jint right, jint bottom, jint top, jint zNear, jint zFar) {
+    glFrustumxOES(
+        (GLfixed)left,
+        (GLfixed)right,
+        (GLfixed)bottom,
+        (GLfixed)top,
+        (GLfixed)zNear,
+        (GLfixed)zFar
+    );
+}
+
+/* void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn ) */
+static void
+android_glGetClipPlanexOES__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray eqn_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *eqn_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *eqn = (GLfixed *) 0;
+
+    if (!eqn_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "eqn == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(eqn_ref) - offset;
+    if (_remaining < 4) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < 4");
+        goto exit;
+    }
+    eqn_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(eqn_ref, (jboolean *)0);
+    eqn = eqn_base + offset;
+
+    glGetClipPlanexOES(
+        (GLenum)pname,
+        (GLfixed *)eqn
+    );
+
+exit:
+    if (eqn_base) {
+        _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn ) */
+static void
+android_glGetClipPlanexOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *eqn = (GLfixed *) 0;
+
+    eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    if (_remaining < 4) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < 4");
+        goto exit;
+    }
+    glGetClipPlanexOES(
+        (GLenum)pname,
+        (GLfixed *)eqn
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */
+static void
+android_glGetFixedvOES__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetFixedvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetFixedvOES ( GLenum pname, GLfixed *params ) */
+static void
+android_glGetFixedvOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetFixedvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params ) */
+static void
+android_glGetLightxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetLightxvOES(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params ) */
+static void
+android_glGetLightxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetLightxvOES(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params ) */
+static void
+android_glGetMaterialxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetMaterialxvOES(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params ) */
+static void
+android_glGetMaterialxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetMaterialxvOES(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexEnvxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexEnvxvOES(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexEnvxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint env, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetTexEnvxvOES(
+        (GLenum)env,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexParameterxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexParameterxvOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexParameterxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetTexParameterxvOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glLightModelxOES ( GLenum pname, GLfixed param ) */
+static void
+android_glLightModelxOES__II
+  (JNIEnv *_env, jobject _this, jint pname, jint param) {
+    glLightModelxOES(
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glLightModelxvOES ( GLenum pname, const GLfixed *params ) */
+static void
+android_glLightModelxvOES__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glLightModelxvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLightModelxvOES ( GLenum pname, const GLfixed *params ) */
+static void
+android_glLightModelxvOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glLightModelxvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glLightxOES ( GLenum light, GLenum pname, GLfixed param ) */
+static void
+android_glLightxOES__III
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jint param) {
+    glLightxOES(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params ) */
+static void
+android_glLightxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glLightxvOES(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params ) */
+static void
+android_glLightxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint light, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glLightxvOES(
+        (GLenum)light,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glLineWidthxOES ( GLfixed width ) */
+static void
+android_glLineWidthxOES__I
+  (JNIEnv *_env, jobject _this, jint width) {
+    glLineWidthxOES(
+        (GLfixed)width
+    );
+}
+
+/* void glLoadMatrixxOES ( const GLfixed *m ) */
+static void
+android_glLoadMatrixxOES___3II
+  (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    GLfixed *m_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    if (!m_ref) {
+        _env->ThrowNew(IAEClass, "m == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(m_ref) - offset;
+    m_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0);
+    m = m_base + offset;
+
+    glLoadMatrixxOES(
+        (GLfixed *)m
+    );
+
+exit:
+    if (m_base) {
+        _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glLoadMatrixxOES ( const GLfixed *m ) */
+static void
+android_glLoadMatrixxOES__Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jobject m_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    glLoadMatrixxOES(
+        (GLfixed *)m
+    );
+    if (_array) {
+        releasePointer(_env, _array, m, JNI_FALSE);
+    }
+}
+
+/* void glMaterialxOES ( GLenum face, GLenum pname, GLfixed param ) */
+static void
+android_glMaterialxOES__III
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jint param) {
+    glMaterialxOES(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params ) */
+static void
+android_glMaterialxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glMaterialxvOES(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params ) */
+static void
+android_glMaterialxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint face, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glMaterialxvOES(
+        (GLenum)face,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glMultMatrixxOES ( const GLfixed *m ) */
+static void
+android_glMultMatrixxOES___3II
+  (JNIEnv *_env, jobject _this, jintArray m_ref, jint offset) {
+    GLfixed *m_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    if (!m_ref) {
+        _env->ThrowNew(IAEClass, "m == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(m_ref) - offset;
+    m_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(m_ref, (jboolean *)0);
+    m = m_base + offset;
+
+    glMultMatrixxOES(
+        (GLfixed *)m
+    );
+
+exit:
+    if (m_base) {
+        _env->ReleasePrimitiveArrayCritical(m_ref, m_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glMultMatrixxOES ( const GLfixed *m ) */
+static void
+android_glMultMatrixxOES__Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jobject m_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *m = (GLfixed *) 0;
+
+    m = (GLfixed *)getPointer(_env, m_buf, &_array, &_remaining);
+    glMultMatrixxOES(
+        (GLfixed *)m
+    );
+    if (_array) {
+        releasePointer(_env, _array, m, JNI_FALSE);
+    }
+}
+
+/* void glMultiTexCoord4xOES ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q ) */
+static void
+android_glMultiTexCoord4xOES__IIIII
+  (JNIEnv *_env, jobject _this, jint target, jint s, jint t, jint r, jint q) {
+    glMultiTexCoord4xOES(
+        (GLenum)target,
+        (GLfixed)s,
+        (GLfixed)t,
+        (GLfixed)r,
+        (GLfixed)q
+    );
+}
+
+/* void glNormal3xOES ( GLfixed nx, GLfixed ny, GLfixed nz ) */
+static void
+android_glNormal3xOES__III
+  (JNIEnv *_env, jobject _this, jint nx, jint ny, jint nz) {
+    glNormal3xOES(
+        (GLfixed)nx,
+        (GLfixed)ny,
+        (GLfixed)nz
+    );
+}
+
+/* void glOrthoxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar ) */
+static void
+android_glOrthoxOES__IIIIII
+  (JNIEnv *_env, jobject _this, jint left, jint right, jint bottom, jint top, jint zNear, jint zFar) {
+    glOrthoxOES(
+        (GLfixed)left,
+        (GLfixed)right,
+        (GLfixed)bottom,
+        (GLfixed)top,
+        (GLfixed)zNear,
+        (GLfixed)zFar
+    );
+}
+
+/* void glPointParameterxOES ( GLenum pname, GLfixed param ) */
+static void
+android_glPointParameterxOES__II
+  (JNIEnv *_env, jobject _this, jint pname, jint param) {
+    glPointParameterxOES(
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glPointParameterxvOES ( GLenum pname, const GLfixed *params ) */
+static void
+android_glPointParameterxvOES__I_3II
+  (JNIEnv *_env, jobject _this, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glPointParameterxvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glPointParameterxvOES ( GLenum pname, const GLfixed *params ) */
+static void
+android_glPointParameterxvOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glPointParameterxvOES(
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glPointSizexOES ( GLfixed size ) */
+static void
+android_glPointSizexOES__I
+  (JNIEnv *_env, jobject _this, jint size) {
+    glPointSizexOES(
+        (GLfixed)size
+    );
+}
+
+/* void glPolygonOffsetxOES ( GLfixed factor, GLfixed units ) */
+static void
+android_glPolygonOffsetxOES__II
+  (JNIEnv *_env, jobject _this, jint factor, jint units) {
+    glPolygonOffsetxOES(
+        (GLfixed)factor,
+        (GLfixed)units
+    );
+}
+
+/* void glRotatexOES ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z ) */
+static void
+android_glRotatexOES__IIII
+  (JNIEnv *_env, jobject _this, jint angle, jint x, jint y, jint z) {
+    glRotatexOES(
+        (GLfixed)angle,
+        (GLfixed)x,
+        (GLfixed)y,
+        (GLfixed)z
+    );
+}
+
+/* void glSampleCoveragexOES ( GLclampx value, GLboolean invert ) */
+static void
+android_glSampleCoveragexOES__IZ
+  (JNIEnv *_env, jobject _this, jint value, jboolean invert) {
+    glSampleCoveragexOES(
+        (GLclampx)value,
+        (GLboolean)invert
+    );
+}
+
+/* void glScalexOES ( GLfixed x, GLfixed y, GLfixed z ) */
+static void
+android_glScalexOES__III
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint z) {
+    glScalexOES(
+        (GLfixed)x,
+        (GLfixed)y,
+        (GLfixed)z
+    );
+}
+
+/* void glTexEnvxOES ( GLenum target, GLenum pname, GLfixed param ) */
+static void
+android_glTexEnvxOES__III
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) {
+    glTexEnvxOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexEnvxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexEnvxvOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexEnvxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glTexEnvxvOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexParameterxOES ( GLenum target, GLenum pname, GLfixed param ) */
+static void
+android_glTexParameterxOES__III
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) {
+    glTexParameterxOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexParameterxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexParameterxvOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexParameterxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glTexParameterxvOES(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTranslatexOES ( GLfixed x, GLfixed y, GLfixed z ) */
+static void
+android_glTranslatexOES__III
+  (JNIEnv *_env, jobject _this, jint x, jint y, jint z) {
+    glTranslatexOES(
+        (GLfixed)x,
+        (GLfixed)y,
+        (GLfixed)z
+    );
+}
+
+/* GLboolean glIsRenderbufferOES ( GLuint renderbuffer ) */
+static jboolean
+android_glIsRenderbufferOES__I
+  (JNIEnv *_env, jobject _this, jint renderbuffer) {
+    _env->ThrowNew(UOEClass,
+        "glIsRenderbufferOES");
+    return JNI_FALSE;
+}
+
+/* void glBindRenderbufferOES ( GLenum target, GLuint renderbuffer ) */
+static void
+android_glBindRenderbufferOES__II
+  (JNIEnv *_env, jobject _this, jint target, jint renderbuffer) {
+    _env->ThrowNew(UOEClass,
+        "glBindRenderbufferOES");
+}
+
+/* void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers ) */
+static void
+android_glDeleteRenderbuffersOES__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
+    _env->ThrowNew(UOEClass,
+        "glDeleteRenderbuffersOES");
+}
+
+/* void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers ) */
+static void
+android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
+    _env->ThrowNew(UOEClass,
+        "glDeleteRenderbuffersOES");
+}
+
+/* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
+static void
+android_glGenRenderbuffersOES__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
+    _env->ThrowNew(UOEClass,
+        "glGenRenderbuffersOES");
+}
+
+/* void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers ) */
+static void
+android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
+    _env->ThrowNew(UOEClass,
+        "glGenRenderbuffersOES");
+}
+
+/* void glRenderbufferStorageOES ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height ) */
+static void
+android_glRenderbufferStorageOES__IIII
+  (JNIEnv *_env, jobject _this, jint target, jint internalformat, jint width, jint height) {
+    _env->ThrowNew(UOEClass,
+        "glRenderbufferStorageOES");
+}
+
+/* void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetRenderbufferParameterivOES__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    _env->ThrowNew(UOEClass,
+        "glGetRenderbufferParameterivOES");
+}
+
+/* void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    _env->ThrowNew(UOEClass,
+        "glGetRenderbufferParameterivOES");
+}
+
+/* GLboolean glIsFramebufferOES ( GLuint framebuffer ) */
+static jboolean
+android_glIsFramebufferOES__I
+  (JNIEnv *_env, jobject _this, jint framebuffer) {
+    _env->ThrowNew(UOEClass,
+        "glIsFramebufferOES");
+    return JNI_FALSE;
+}
+
+/* void glBindFramebufferOES ( GLenum target, GLuint framebuffer ) */
+static void
+android_glBindFramebufferOES__II
+  (JNIEnv *_env, jobject _this, jint target, jint framebuffer) {
+    _env->ThrowNew(UOEClass,
+        "glBindFramebufferOES");
+}
+
+/* void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers ) */
+static void
+android_glDeleteFramebuffersOES__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
+    _env->ThrowNew(UOEClass,
+        "glDeleteFramebuffersOES");
+}
+
+/* void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers ) */
+static void
+android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
+    _env->ThrowNew(UOEClass,
+        "glDeleteFramebuffersOES");
+}
+
+/* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
+static void
+android_glGenFramebuffersOES__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
+    _env->ThrowNew(UOEClass,
+        "glGenFramebuffersOES");
+}
+
+/* void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers ) */
+static void
+android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
+    _env->ThrowNew(UOEClass,
+        "glGenFramebuffersOES");
+}
+
+/* GLenum glCheckFramebufferStatusOES ( GLenum target ) */
+static jint
+android_glCheckFramebufferStatusOES__I
+  (JNIEnv *_env, jobject _this, jint target) {
+    _env->ThrowNew(UOEClass,
+        "glCheckFramebufferStatusOES");
+    return 0;
+}
+
+/* void glFramebufferRenderbufferOES ( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer ) */
+static void
+android_glFramebufferRenderbufferOES__IIII
+  (JNIEnv *_env, jobject _this, jint target, jint attachment, jint renderbuffertarget, jint renderbuffer) {
+    _env->ThrowNew(UOEClass,
+        "glFramebufferRenderbufferOES");
+}
+
+/* void glFramebufferTexture2DOES ( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level ) */
+static void
+android_glFramebufferTexture2DOES__IIIII
+  (JNIEnv *_env, jobject _this, jint target, jint attachment, jint textarget, jint texture, jint level) {
+    _env->ThrowNew(UOEClass,
+        "glFramebufferTexture2DOES");
+}
+
+/* void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
+static void
+android_glGetFramebufferAttachmentParameterivOES__III_3II
+  (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
+    _env->ThrowNew(UOEClass,
+        "glGetFramebufferAttachmentParameterivOES");
+}
+
+/* void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params ) */
+static void
+android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
+    _env->ThrowNew(UOEClass,
+        "glGetFramebufferAttachmentParameterivOES");
+}
+
+/* void glGenerateMipmapOES ( GLenum target ) */
+static void
+android_glGenerateMipmapOES__I
+  (JNIEnv *_env, jobject _this, jint target) {
+    _env->ThrowNew(UOEClass,
+        "glGenerateMipmapOES");
+}
+
+/* void glCurrentPaletteMatrixOES ( GLuint matrixpaletteindex ) */
+static void
+android_glCurrentPaletteMatrixOES__I
+  (JNIEnv *_env, jobject _this, jint matrixpaletteindex) {
+    _env->ThrowNew(UOEClass,
+        "glCurrentPaletteMatrixOES");
+}
+
+/* void glLoadPaletteFromModelViewMatrixOES ( void ) */
+static void
+android_glLoadPaletteFromModelViewMatrixOES__
+  (JNIEnv *_env, jobject _this) {
+    _env->ThrowNew(UOEClass,
+        "glLoadPaletteFromModelViewMatrixOES");
+}
+
+/* void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) */
+static void
+android_glMatrixIndexPointerOES__IIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf) {
+    _env->ThrowNew(UOEClass,
+        "glMatrixIndexPointerOES");
+}
+
+/* void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) */
+static void
+android_glWeightPointerOES__IIILjava_nio_Buffer_2
+  (JNIEnv *_env, jobject _this, jint size, jint type, jint stride, jobject pointer_buf) {
+    _env->ThrowNew(UOEClass,
+        "glWeightPointerOES");
+}
+
+/* void glDepthRangefOES ( GLclampf zNear, GLclampf zFar ) */
+static void
+android_glDepthRangefOES__FF
+  (JNIEnv *_env, jobject _this, jfloat zNear, jfloat zFar) {
+    glDepthRangefOES(
+        (GLclampf)zNear,
+        (GLclampf)zFar
+    );
+}
+
+/* void glFrustumfOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
+static void
+android_glFrustumfOES__FFFFFF
+  (JNIEnv *_env, jobject _this, jfloat left, jfloat right, jfloat bottom, jfloat top, jfloat zNear, jfloat zFar) {
+    glFrustumfOES(
+        (GLfloat)left,
+        (GLfloat)right,
+        (GLfloat)bottom,
+        (GLfloat)top,
+        (GLfloat)zNear,
+        (GLfloat)zFar
+    );
+}
+
+/* void glOrthofOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */
+static void
+android_glOrthofOES__FFFFFF
+  (JNIEnv *_env, jobject _this, jfloat left, jfloat right, jfloat bottom, jfloat top, jfloat zNear, jfloat zFar) {
+    glOrthofOES(
+        (GLfloat)left,
+        (GLfloat)right,
+        (GLfloat)bottom,
+        (GLfloat)top,
+        (GLfloat)zNear,
+        (GLfloat)zFar
+    );
+}
+
+/* void glClipPlanefOES ( GLenum plane, const GLfloat *equation ) */
+static void
+android_glClipPlanefOES__I_3FI
+  (JNIEnv *_env, jobject _this, jint plane, jfloatArray equation_ref, jint offset) {
+    GLfloat *equation_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *equation = (GLfloat *) 0;
+
+    if (!equation_ref) {
+        _env->ThrowNew(IAEClass, "equation == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(equation_ref) - offset;
+    equation_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(equation_ref, (jboolean *)0);
+    equation = equation_base + offset;
+
+    glClipPlanefOES(
+        (GLenum)plane,
+        (GLfloat *)equation
+    );
+
+exit:
+    if (equation_base) {
+        _env->ReleasePrimitiveArrayCritical(equation_ref, equation_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glClipPlanefOES ( GLenum plane, const GLfloat *equation ) */
+static void
+android_glClipPlanefOES__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint plane, jobject equation_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *equation = (GLfloat *) 0;
+
+    equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
+    glClipPlanefOES(
+        (GLenum)plane,
+        (GLfloat *)equation
+    );
+    if (_array) {
+        releasePointer(_env, _array, equation, JNI_FALSE);
+    }
+}
+
+/* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */
+static void
+android_glGetClipPlanefOES__I_3FI
+  (JNIEnv *_env, jobject _this, jint pname, jfloatArray eqn_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *eqn_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *eqn = (GLfloat *) 0;
+
+    if (!eqn_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "eqn == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(eqn_ref) - offset;
+    if (_remaining < 4) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "length - offset < 4");
+        goto exit;
+    }
+    eqn_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(eqn_ref, (jboolean *)0);
+    eqn = eqn_base + offset;
+
+    glGetClipPlanefOES(
+        (GLenum)pname,
+        (GLfloat *)eqn
+    );
+
+exit:
+    if (eqn_base) {
+        _env->ReleasePrimitiveArrayCritical(eqn_ref, eqn_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn ) */
+static void
+android_glGetClipPlanefOES__ILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jobject eqn_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *eqn = (GLfloat *) 0;
+
+    eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
+    if (_remaining < 4) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "remaining() < 4");
+        goto exit;
+    }
+    glGetClipPlanefOES(
+        (GLenum)pname,
+        (GLfloat *)eqn
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, eqn, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glClearDepthfOES ( GLclampf depth ) */
+static void
+android_glClearDepthfOES__F
+  (JNIEnv *_env, jobject _this, jfloat depth) {
+    glClearDepthfOES(
+        (GLclampf)depth
+    );
+}
+
+/* void glTexGenfOES ( GLenum coord, GLenum pname, GLfloat param ) */
+static void
+android_glTexGenfOES__IIF
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloat param) {
+    glTexGenfOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfloat)param
+    );
+}
+
+/* void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params ) */
+static void
+android_glTexGenfvOES__II_3FI
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexGenfvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params ) */
+static void
+android_glTexGenfvOES__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    glTexGenfvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexGeniOES ( GLenum coord, GLenum pname, GLint param ) */
+static void
+android_glTexGeniOES__III
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
+    glTexGeniOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLint)param
+    );
+}
+
+/* void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params ) */
+static void
+android_glTexGenivOES__II_3II
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexGenivOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params ) */
+static void
+android_glTexGenivOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    glTexGenivOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexGenxOES ( GLenum coord, GLenum pname, GLfixed param ) */
+static void
+android_glTexGenxOES__III
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
+    glTexGenxOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfixed)param
+    );
+}
+
+/* void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexGenxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexGenxvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+}
+
+/* void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params ) */
+static void
+android_glTexGenxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glTexGenxvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexGenfvOES__II_3FI
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexGenfvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexGenfvOES__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetTexGenfvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params ) */
+static void
+android_glGetTexGenivOES__II_3II
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexGenivOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params ) */
+static void
+android_glGetTexGenivOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetTexGenivOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+/* void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexGenxvOES__II_3II
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    GLfixed *params_base = (GLfixed *) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "params == null");
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _env->ThrowNew(IAEClass, "offset < 0");
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfixed *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexGenxvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+}
+
+/* void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params ) */
+static void
+android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    jarray _array = (jarray) 0;
+    jint _remaining;
+    GLfixed *params = (GLfixed *) 0;
+
+    params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
+    glGetTexGenxvOES(
+        (GLenum)coord,
+        (GLenum)pname,
+        (GLfixed *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+}
+
+static const char *classPathName = "android/opengl/GLES11Ext";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"glBlendEquationSeparateOES", "(II)V", (void *) android_glBlendEquationSeparateOES__II },
+{"glBlendFuncSeparateOES", "(IIII)V", (void *) android_glBlendFuncSeparateOES__IIII },
+{"glBlendEquationOES", "(I)V", (void *) android_glBlendEquationOES__I },
+{"glDrawTexsOES", "(SSSSS)V", (void *) android_glDrawTexsOES__SSSSS },
+{"glDrawTexiOES", "(IIIII)V", (void *) android_glDrawTexiOES__IIIII },
+{"glDrawTexxOES", "(IIIII)V", (void *) android_glDrawTexxOES__IIIII },
+{"glDrawTexsvOES", "([SI)V", (void *) android_glDrawTexsvOES___3SI },
+{"glDrawTexsvOES", "(Ljava/nio/ShortBuffer;)V", (void *) android_glDrawTexsvOES__Ljava_nio_ShortBuffer_2 },
+{"glDrawTexivOES", "([II)V", (void *) android_glDrawTexivOES___3II },
+{"glDrawTexivOES", "(Ljava/nio/IntBuffer;)V", (void *) android_glDrawTexivOES__Ljava_nio_IntBuffer_2 },
+{"glDrawTexxvOES", "([II)V", (void *) android_glDrawTexxvOES___3II },
+{"glDrawTexxvOES", "(Ljava/nio/IntBuffer;)V", (void *) android_glDrawTexxvOES__Ljava_nio_IntBuffer_2 },
+{"glDrawTexfOES", "(FFFFF)V", (void *) android_glDrawTexfOES__FFFFF },
+{"glDrawTexfvOES", "([FI)V", (void *) android_glDrawTexfvOES___3FI },
+{"glDrawTexfvOES", "(Ljava/nio/FloatBuffer;)V", (void *) android_glDrawTexfvOES__Ljava_nio_FloatBuffer_2 },
+{"glEGLImageTargetTexture2DOES", "(ILjava/nio/Buffer;)V", (void *) android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2 },
+{"glEGLImageTargetRenderbufferStorageOES", "(ILjava/nio/Buffer;)V", (void *) android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2 },
+{"glAlphaFuncxOES", "(II)V", (void *) android_glAlphaFuncxOES__II },
+{"glClearColorxOES", "(IIII)V", (void *) android_glClearColorxOES__IIII },
+{"glClearDepthxOES", "(I)V", (void *) android_glClearDepthxOES__I },
+{"glClipPlanexOES", "(I[II)V", (void *) android_glClipPlanexOES__I_3II },
+{"glClipPlanexOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glClipPlanexOES__ILjava_nio_IntBuffer_2 },
+{"glColor4xOES", "(IIII)V", (void *) android_glColor4xOES__IIII },
+{"glDepthRangexOES", "(II)V", (void *) android_glDepthRangexOES__II },
+{"glFogxOES", "(II)V", (void *) android_glFogxOES__II },
+{"glFogxvOES", "(I[II)V", (void *) android_glFogxvOES__I_3II },
+{"glFogxvOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glFogxvOES__ILjava_nio_IntBuffer_2 },
+{"glFrustumxOES", "(IIIIII)V", (void *) android_glFrustumxOES__IIIIII },
+{"glGetClipPlanexOES", "(I[II)V", (void *) android_glGetClipPlanexOES__I_3II },
+{"glGetClipPlanexOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetClipPlanexOES__ILjava_nio_IntBuffer_2 },
+{"glGetFixedvOES", "(I[II)V", (void *) android_glGetFixedvOES__I_3II },
+{"glGetFixedvOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glGetFixedvOES__ILjava_nio_IntBuffer_2 },
+{"glGetLightxvOES", "(II[II)V", (void *) android_glGetLightxvOES__II_3II },
+{"glGetLightxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetLightxvOES__IILjava_nio_IntBuffer_2 },
+{"glGetMaterialxvOES", "(II[II)V", (void *) android_glGetMaterialxvOES__II_3II },
+{"glGetMaterialxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetMaterialxvOES__IILjava_nio_IntBuffer_2 },
+{"glGetTexEnvxvOES", "(II[II)V", (void *) android_glGetTexEnvxvOES__II_3II },
+{"glGetTexEnvxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexEnvxvOES__IILjava_nio_IntBuffer_2 },
+{"glGetTexParameterxvOES", "(II[II)V", (void *) android_glGetTexParameterxvOES__II_3II },
+{"glGetTexParameterxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexParameterxvOES__IILjava_nio_IntBuffer_2 },
+{"glLightModelxOES", "(II)V", (void *) android_glLightModelxOES__II },
+{"glLightModelxvOES", "(I[II)V", (void *) android_glLightModelxvOES__I_3II },
+{"glLightModelxvOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glLightModelxvOES__ILjava_nio_IntBuffer_2 },
+{"glLightxOES", "(III)V", (void *) android_glLightxOES__III },
+{"glLightxvOES", "(II[II)V", (void *) android_glLightxvOES__II_3II },
+{"glLightxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glLightxvOES__IILjava_nio_IntBuffer_2 },
+{"glLineWidthxOES", "(I)V", (void *) android_glLineWidthxOES__I },
+{"glLoadMatrixxOES", "([II)V", (void *) android_glLoadMatrixxOES___3II },
+{"glLoadMatrixxOES", "(Ljava/nio/IntBuffer;)V", (void *) android_glLoadMatrixxOES__Ljava_nio_IntBuffer_2 },
+{"glMaterialxOES", "(III)V", (void *) android_glMaterialxOES__III },
+{"glMaterialxvOES", "(II[II)V", (void *) android_glMaterialxvOES__II_3II },
+{"glMaterialxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glMaterialxvOES__IILjava_nio_IntBuffer_2 },
+{"glMultMatrixxOES", "([II)V", (void *) android_glMultMatrixxOES___3II },
+{"glMultMatrixxOES", "(Ljava/nio/IntBuffer;)V", (void *) android_glMultMatrixxOES__Ljava_nio_IntBuffer_2 },
+{"glMultiTexCoord4xOES", "(IIIII)V", (void *) android_glMultiTexCoord4xOES__IIIII },
+{"glNormal3xOES", "(III)V", (void *) android_glNormal3xOES__III },
+{"glOrthoxOES", "(IIIIII)V", (void *) android_glOrthoxOES__IIIIII },
+{"glPointParameterxOES", "(II)V", (void *) android_glPointParameterxOES__II },
+{"glPointParameterxvOES", "(I[II)V", (void *) android_glPointParameterxvOES__I_3II },
+{"glPointParameterxvOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glPointParameterxvOES__ILjava_nio_IntBuffer_2 },
+{"glPointSizexOES", "(I)V", (void *) android_glPointSizexOES__I },
+{"glPolygonOffsetxOES", "(II)V", (void *) android_glPolygonOffsetxOES__II },
+{"glRotatexOES", "(IIII)V", (void *) android_glRotatexOES__IIII },
+{"glSampleCoveragexOES", "(IZ)V", (void *) android_glSampleCoveragexOES__IZ },
+{"glScalexOES", "(III)V", (void *) android_glScalexOES__III },
+{"glTexEnvxOES", "(III)V", (void *) android_glTexEnvxOES__III },
+{"glTexEnvxvOES", "(II[II)V", (void *) android_glTexEnvxvOES__II_3II },
+{"glTexEnvxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexEnvxvOES__IILjava_nio_IntBuffer_2 },
+{"glTexParameterxOES", "(III)V", (void *) android_glTexParameterxOES__III },
+{"glTexParameterxvOES", "(II[II)V", (void *) android_glTexParameterxvOES__II_3II },
+{"glTexParameterxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexParameterxvOES__IILjava_nio_IntBuffer_2 },
+{"glTranslatexOES", "(III)V", (void *) android_glTranslatexOES__III },
+{"glIsRenderbufferOES", "(I)Z", (void *) android_glIsRenderbufferOES__I },
+{"glBindRenderbufferOES", "(II)V", (void *) android_glBindRenderbufferOES__II },
+{"glDeleteRenderbuffersOES", "(I[II)V", (void *) android_glDeleteRenderbuffersOES__I_3II },
+{"glDeleteRenderbuffersOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2 },
+{"glGenRenderbuffersOES", "(I[II)V", (void *) android_glGenRenderbuffersOES__I_3II },
+{"glGenRenderbuffersOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2 },
+{"glRenderbufferStorageOES", "(IIII)V", (void *) android_glRenderbufferStorageOES__IIII },
+{"glGetRenderbufferParameterivOES", "(II[II)V", (void *) android_glGetRenderbufferParameterivOES__II_3II },
+{"glGetRenderbufferParameterivOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2 },
+{"glIsFramebufferOES", "(I)Z", (void *) android_glIsFramebufferOES__I },
+{"glBindFramebufferOES", "(II)V", (void *) android_glBindFramebufferOES__II },
+{"glDeleteFramebuffersOES", "(I[II)V", (void *) android_glDeleteFramebuffersOES__I_3II },
+{"glDeleteFramebuffersOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2 },
+{"glGenFramebuffersOES", "(I[II)V", (void *) android_glGenFramebuffersOES__I_3II },
+{"glGenFramebuffersOES", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2 },
+{"glCheckFramebufferStatusOES", "(I)I", (void *) android_glCheckFramebufferStatusOES__I },
+{"glFramebufferRenderbufferOES", "(IIII)V", (void *) android_glFramebufferRenderbufferOES__IIII },
+{"glFramebufferTexture2DOES", "(IIIII)V", (void *) android_glFramebufferTexture2DOES__IIIII },
+{"glGetFramebufferAttachmentParameterivOES", "(III[II)V", (void *) android_glGetFramebufferAttachmentParameterivOES__III_3II },
+{"glGetFramebufferAttachmentParameterivOES", "(IIILjava/nio/IntBuffer;)V", (void *) android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2 },
+{"glGenerateMipmapOES", "(I)V", (void *) android_glGenerateMipmapOES__I },
+{"glCurrentPaletteMatrixOES", "(I)V", (void *) android_glCurrentPaletteMatrixOES__I },
+{"glLoadPaletteFromModelViewMatrixOES", "()V", (void *) android_glLoadPaletteFromModelViewMatrixOES__ },
+{"glMatrixIndexPointerOES", "(IIILjava/nio/Buffer;)V", (void *) android_glMatrixIndexPointerOES__IIILjava_nio_Buffer_2 },
+{"glWeightPointerOES", "(IIILjava/nio/Buffer;)V", (void *) android_glWeightPointerOES__IIILjava_nio_Buffer_2 },
+{"glDepthRangefOES", "(FF)V", (void *) android_glDepthRangefOES__FF },
+{"glFrustumfOES", "(FFFFFF)V", (void *) android_glFrustumfOES__FFFFFF },
+{"glOrthofOES", "(FFFFFF)V", (void *) android_glOrthofOES__FFFFFF },
+{"glClipPlanefOES", "(I[FI)V", (void *) android_glClipPlanefOES__I_3FI },
+{"glClipPlanefOES", "(ILjava/nio/FloatBuffer;)V", (void *) android_glClipPlanefOES__ILjava_nio_FloatBuffer_2 },
+{"glGetClipPlanefOES", "(I[FI)V", (void *) android_glGetClipPlanefOES__I_3FI },
+{"glGetClipPlanefOES", "(ILjava/nio/FloatBuffer;)V", (void *) android_glGetClipPlanefOES__ILjava_nio_FloatBuffer_2 },
+{"glClearDepthfOES", "(F)V", (void *) android_glClearDepthfOES__F },
+{"glTexGenfOES", "(IIF)V", (void *) android_glTexGenfOES__IIF },
+{"glTexGenfvOES", "(II[FI)V", (void *) android_glTexGenfvOES__II_3FI },
+{"glTexGenfvOES", "(IILjava/nio/FloatBuffer;)V", (void *) android_glTexGenfvOES__IILjava_nio_FloatBuffer_2 },
+{"glTexGeniOES", "(III)V", (void *) android_glTexGeniOES__III },
+{"glTexGenivOES", "(II[II)V", (void *) android_glTexGenivOES__II_3II },
+{"glTexGenivOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexGenivOES__IILjava_nio_IntBuffer_2 },
+{"glTexGenxOES", "(III)V", (void *) android_glTexGenxOES__III },
+{"glTexGenxvOES", "(II[II)V", (void *) android_glTexGenxvOES__II_3II },
+{"glTexGenxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexGenxvOES__IILjava_nio_IntBuffer_2 },
+{"glGetTexGenfvOES", "(II[FI)V", (void *) android_glGetTexGenfvOES__II_3FI },
+{"glGetTexGenfvOES", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetTexGenfvOES__IILjava_nio_FloatBuffer_2 },
+{"glGetTexGenivOES", "(II[II)V", (void *) android_glGetTexGenivOES__II_3II },
+{"glGetTexGenivOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexGenivOES__IILjava_nio_IntBuffer_2 },
+{"glGetTexGenxvOES", "(II[II)V", (void *) android_glGetTexGenxvOES__II_3II },
+{"glGetTexGenxvOES", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexGenxvOES__IILjava_nio_IntBuffer_2 },
+};
+
+int register_android_opengl_jni_GLES11Ext(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index 062f893..b320c09 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -52,12 +52,11 @@
 
 static native_data_t *nat = NULL;  // global native data
 
-extern event_loop_native_data_t *event_loop_nat;  // for the event loop JNIEnv
 #endif
 
 #ifdef HAVE_BLUETOOTH
-static void onConnectSinkResult(DBusMessage *msg, void *user);
-static void onDisconnectSinkResult(DBusMessage *msg, void *user);
+static void onConnectSinkResult(DBusMessage *msg, void *user, void *nat);
+static void onDisconnectSinkResult(DBusMessage *msg, void *user, void *nat);
 #endif
 
 /* Returns true on success (even if adapter is present but disabled).
@@ -175,7 +174,8 @@
 
         bool ret =
             dbus_func_args_async(env, nat->conn, -1,
-                           onConnectSinkResult, (void *)c_path_copy, c_path,
+                           onConnectSinkResult, (void *)c_path_copy, nat,
+                           c_path,
                            "org.bluez.audio.Sink", "Connect",
                            DBUS_TYPE_INVALID);
 
@@ -202,7 +202,8 @@
 
         bool ret =
             dbus_func_args_async(env, nat->conn, -1,
-                           onDisconnectSinkResult, (void *)c_path_copy, c_path,
+                           onDisconnectSinkResult, (void *)c_path_copy, nat,
+                           c_path,
                            "org.bluez.audio.Sink", "Disconnect",
                            DBUS_TYPE_INVALID);
         env->ReleaseStringUTFChars(path, c_path);
@@ -233,13 +234,13 @@
 }
 
 #ifdef HAVE_BLUETOOTH
-static void onConnectSinkResult(DBusMessage *msg, void *user) {
+static void onConnectSinkResult(DBusMessage *msg, void *user, void *natData) {
     LOGV(__FUNCTION__);
 
     char *c_path = (char *)user;
     DBusError err;
     dbus_error_init(&err);
-    JNIEnv *env = event_loop_nat->env;
+    JNIEnv *env = nat->env;
 
     LOGV("... path = %s", c_path);
     if (dbus_set_error_from_message(&err, msg)) {
@@ -258,13 +259,13 @@
     free(c_path);
 }
 
-static void onDisconnectSinkResult(DBusMessage *msg, void *user) {
+static void onDisconnectSinkResult(DBusMessage *msg, void *user, void *natData) {
     LOGV(__FUNCTION__);
 
     char *c_path = (char *)user;
     DBusError err;
     dbus_error_init(&err);
-    JNIEnv *env = event_loop_nat->env;
+    JNIEnv *env = nat->env;
 
     LOGV("... path = %s", c_path);
     if (dbus_set_error_from_message(&err, msg)) {
diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothDeviceService.cpp
index a0e0b84..b6e9798 100644
--- a/core/jni/android_server_BluetoothDeviceService.cpp
+++ b/core/jni/android_server_BluetoothDeviceService.cpp
@@ -50,6 +50,7 @@
 // We initialize these variables when we load class
 // android.server.BluetoothDeviceService
 static jfieldID field_mNativeData;
+static jfieldID field_mEventLoop;
 
 typedef struct {
     JNIEnv *env;
@@ -57,8 +58,10 @@
     const char *adapter;  // dbus object name of the local adapter
 } native_data_t;
 
-void onCreateBondingResult(DBusMessage *msg, void *user);
-void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user);
+extern event_loop_native_data_t *get_EventLoop_native_data(JNIEnv *,
+                                                           jobject);
+void onCreateBondingResult(DBusMessage *msg, void *user, void *nat);
+void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user, void *nat);
 
 /** Get native data stored in the opaque (Java code maintained) pointer mNativeData
  *  Perform quick sanity check, if there are any problems return NULL
@@ -78,6 +81,8 @@
     LOGV(__FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     field_mNativeData = get_field(env, clazz, "mNativeData", "I");
+    field_mEventLoop = get_field(env, clazz, "mEventLoop",
+            "Landroid/server/BluetoothEventLoop;");
 #endif
 }
 
@@ -472,14 +477,19 @@
     LOGV(__FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
-    if (nat) {
+    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
+    struct event_loop_native_data_t *eventLoopNat =
+            get_EventLoop_native_data(env, eventLoop);
+
+    if (nat && eventLoopNat) {
         const char *c_address = env->GetStringUTFChars(address, NULL);
         LOGV("... address = %s", c_address);
         char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
         strlcpy(context_address, c_address, BTADDR_SIZE);  // for callback
         bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms,
                                         onCreateBondingResult, // callback
-                                        context_address, // user data
+                                        context_address,
+                                        eventLoopNat,
                                         nat->adapter,
                                         DBUS_CLASS_NAME, "CreateBonding",
                                         DBUS_TYPE_STRING, &c_address,
@@ -856,7 +866,10 @@
 #ifdef HAVE_BLUETOOTH
     LOGV(__FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
-    if (nat) {
+    jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
+    struct event_loop_native_data_t *eventLoopNat =
+            get_EventLoop_native_data(env, eventLoop);
+    if (nat && eventLoopNat) {
         const char *c_address = env->GetStringUTFChars(address, NULL);
         char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char));
         strlcpy(context_address, c_address, BTADDR_SIZE);
@@ -866,6 +879,7 @@
 
         bool ret = dbus_func_args_async(env, nat->conn, 20000,  // ms
                            onGetRemoteServiceChannelResult, context_address,
+                           eventLoopNat,
                            nat->adapter,
                            DBUS_CLASS_NAME, "GetRemoteServiceChannel",
                            DBUS_TYPE_STRING, &c_address,
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index c03bab6..7c5da5b 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -18,6 +18,7 @@
 
 #include "android_bluetooth_common.h"
 #include "android_runtime/AndroidRuntime.h"
+#include "cutils/sockets.h"
 #include "JNIHelp.h"
 #include "jni.h"
 #include "utils/Log.h"
@@ -65,14 +66,15 @@
 
 typedef event_loop_native_data_t native_data_t;
 
-// Only valid during waitForAndDispatchEventNative()
-native_data_t *event_loop_nat;
-
 static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
     return (native_data_t *)(env->GetIntField(object,
                                                  field_mNativeData));
 }
 
+native_data_t *get_EventLoop_native_data(JNIEnv *env, jobject object) {
+    return get_native_data(env, object);
+}
+
 #endif
 static void classInitNative(JNIEnv* env, jclass clazz) {
     LOGV(__FUNCTION__);
@@ -115,6 +117,10 @@
         LOGE("%s: out of memory!", __FUNCTION__);
         return;
     }
+    memset(nat, 0, sizeof(native_data_t));
+
+    pthread_mutex_init(&(nat->thread_mutex), NULL);
+
     env->SetIntField(object, field_mNativeData, (jint)nat);
 
     {
@@ -135,6 +141,9 @@
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat =
             (native_data_t *)env->GetIntField(object, field_mNativeData);
+
+    pthread_mutex_destroy(&(nat->thread_mutex));
+
     if (nat) {
         free(nat);
     }
@@ -151,13 +160,11 @@
 static const DBusObjectPathVTable agent_vtable = {
     NULL, agent_event_filter, NULL, NULL, NULL, NULL
 };
-#endif
 
-static jboolean setUpEventLoopNative(JNIEnv *env, jobject object) {
-#ifdef HAVE_BLUETOOTH
+
+static jboolean setUpEventLoop(native_data_t *nat) {
     LOGV(__FUNCTION__);
     dbus_threads_init_default();
-    native_data_t *nat = get_native_data(env, object);
     DBusError err;
     dbus_error_init(&err);
 
@@ -207,7 +214,7 @@
         // Add an object handler for passkey agent method calls
         const char *path = "/android/bluetooth/Agent";
         if (!dbus_connection_register_object_path(nat->conn, path,
-                &agent_vtable, NULL)) {
+                &agent_vtable, nat)) {
             LOGE("%s: Can't register object path %s for agent!",
                  __FUNCTION__, path);
             return JNI_FALSE;
@@ -217,7 +224,7 @@
         // trying for 10 seconds.
         int attempt;
         for (attempt = 0; attempt < 1000; attempt++) {
-            DBusMessage *reply = dbus_func_args_error(env, nat->conn, &err,
+            DBusMessage *reply = dbus_func_args_error(NULL, nat->conn, &err,
                     BLUEZ_DBUS_BASE_PATH,
                     "org.bluez.Security", "RegisterDefaultPasskeyAgent",
                     DBUS_TYPE_STRING, &path,
@@ -245,7 +252,7 @@
         }
 
         // Now register the Auth agent
-        DBusMessage *reply = dbus_func_args_error(env, nat->conn, &err,
+        DBusMessage *reply = dbus_func_args_error(NULL, nat->conn, &err,
                 BLUEZ_DBUS_BASE_PATH,
                 "org.bluez.Security", "RegisterDefaultAuthorizationAgent",
                 DBUS_TYPE_STRING, &path,
@@ -259,14 +266,11 @@
         return JNI_TRUE;
     }
 
-#endif
     return JNI_FALSE;
 }
 
-static void tearDownEventLoopNative(JNIEnv *env, jobject object) {
+static void tearDownEventLoop(native_data_t *nat) {
     LOGV(__FUNCTION__);
-#ifdef HAVE_BLUETOOTH
-    native_data_t *nat = get_native_data(env, object);
     if (nat != NULL && nat->conn != NULL) {
 
         DBusError err;
@@ -274,14 +278,14 @@
 
         const char *path = "/android/bluetooth/Agent";
         DBusMessage *reply =
-            dbus_func_args(env, nat->conn, BLUEZ_DBUS_BASE_PATH,
+            dbus_func_args(NULL, nat->conn, BLUEZ_DBUS_BASE_PATH,
                     "org.bluez.Security", "UnregisterDefaultPasskeyAgent",
                     DBUS_TYPE_STRING, &path,
                     DBUS_TYPE_INVALID);
         if (reply) dbus_message_unref(reply);
 
         reply =
-            dbus_func_args(env, nat->conn, BLUEZ_DBUS_BASE_PATH,
+            dbus_func_args(NULL, nat->conn, BLUEZ_DBUS_BASE_PATH,
                     "org.bluez.Security", "UnregisterDefaultAuthorizationAgent",
                     DBUS_TYPE_STRING, &path,
                     DBUS_TYPE_INVALID);
@@ -322,7 +326,308 @@
 
         dbus_connection_remove_filter(nat->conn, event_filter, nat);
     }
-#endif
+}
+
+
+#define EVENT_LOOP_EXIT 1
+#define EVENT_LOOP_ADD  2
+#define EVENT_LOOP_REMOVE 3
+
+dbus_bool_t dbusAddWatch(DBusWatch *watch, void *data) {
+    native_data_t *nat = (native_data_t *)data;
+
+    if (dbus_watch_get_enabled(watch)) {
+        // note that we can't just send the watch and inspect it later
+        // because we may get a removeWatch call before this data is reacted
+        // to by our eventloop and remove this watch..  reading the add first
+        // and then inspecting the recently deceased watch would be bad.
+        char control = EVENT_LOOP_ADD;
+        write(nat->controlFdW, &control, sizeof(char));
+
+        int fd = dbus_watch_get_fd(watch);
+        write(nat->controlFdW, &fd, sizeof(int));
+
+        unsigned int flags = dbus_watch_get_flags(watch);
+        write(nat->controlFdW, &flags, sizeof(unsigned int));
+
+        write(nat->controlFdW, &watch, sizeof(DBusWatch*));
+    }
+    return true;
+}
+
+void dbusRemoveWatch(DBusWatch *watch, void *data) {
+    native_data_t *nat = (native_data_t *)data;
+
+    char control = EVENT_LOOP_REMOVE;
+    write(nat->controlFdW, &control, sizeof(char));
+
+    int fd = dbus_watch_get_fd(watch);
+    write(nat->controlFdW, &fd, sizeof(int));
+
+    unsigned int flags = dbus_watch_get_flags(watch);
+    write(nat->controlFdW, &flags, sizeof(unsigned int));
+}
+
+void dbusToggleWatch(DBusWatch *watch, void *data) {
+    if (dbus_watch_get_enabled(watch)) {
+        dbusAddWatch(watch, data);
+    } else {
+        dbusRemoveWatch(watch, data);
+    }
+}
+
+static void handleWatchAdd(native_data_t *nat) {
+    DBusWatch *watch;
+    int newFD;
+    unsigned int flags;
+
+    read(nat->controlFdR, &newFD, sizeof(int));
+    read(nat->controlFdR, &flags, sizeof(unsigned int));
+    read(nat->controlFdR, &watch, sizeof(DBusWatch *));
+    int events = (flags & DBUS_WATCH_READABLE ? POLLIN : 0)
+            | (flags & DBUS_WATCH_WRITABLE ? POLLOUT : 0);
+
+    for (int y = 0; y<nat->pollMemberCount; y++) {
+        if ((nat->pollData[y].fd == newFD) &&
+                (nat->pollData[y].events == events)) {
+            LOGV("DBusWatch duplicate add");
+            return;
+        }
+    }
+    if (nat->pollMemberCount == nat->pollDataSize) {
+        LOGV("Bluetooth EventLoop poll struct growing");
+        struct pollfd *temp = (struct pollfd *)malloc(
+                sizeof(struct pollfd) * (nat->pollMemberCount+1));
+        if (!temp) {
+            return;
+        }
+        memcpy(temp, nat->pollData, sizeof(struct pollfd) *
+                nat->pollMemberCount);
+        free(nat->pollData);
+        nat->pollData = temp;
+        DBusWatch **temp2 = (DBusWatch **)malloc(sizeof(DBusWatch *) *
+                (nat->pollMemberCount+1));
+        if (!temp2) {
+            return;
+        }
+        memcpy(temp2, nat->watchData, sizeof(DBusWatch *) *
+                nat->pollMemberCount);
+        free(nat->watchData);
+        nat->watchData = temp2;
+        nat->pollDataSize++;
+    }
+    nat->pollData[nat->pollMemberCount].fd = newFD;
+    nat->pollData[nat->pollMemberCount].revents = 0;
+    nat->pollData[nat->pollMemberCount].events = events;
+    nat->watchData[nat->pollMemberCount] = watch;
+    nat->pollMemberCount++;
+}
+
+static void handleWatchRemove(native_data_t *nat) {
+    int removeFD;
+    unsigned int flags;
+
+    read(nat->controlFdR, &removeFD, sizeof(int));
+    read(nat->controlFdR, &flags, sizeof(unsigned int));
+    int events = (flags & DBUS_WATCH_READABLE ? POLLIN : 0)
+            | (flags & DBUS_WATCH_WRITABLE ? POLLOUT : 0);
+
+    for (int y = 0; y < nat->pollMemberCount; y++) {
+        if ((nat->pollData[y].fd == removeFD) &&
+                (nat->pollData[y].events == events)) {
+            int newCount = --nat->pollMemberCount;
+            // copy the last live member over this one
+            nat->pollData[y].fd = nat->pollData[newCount].fd;
+            nat->pollData[y].events = nat->pollData[newCount].events;
+            nat->pollData[y].revents = nat->pollData[newCount].revents;
+            nat->watchData[y] = nat->watchData[newCount];
+            return;
+        }
+    }
+    LOGW("WatchRemove given with unknown watch");
+}
+
+static void *eventLoopMain(void *ptr) {
+    native_data_t *nat = (native_data_t *)ptr;
+    JNIEnv *env;
+
+    JavaVMAttachArgs args;
+    char name[] = "BT EventLoop";
+    args.version = nat->envVer;
+    args.name = name;
+    args.group = NULL;
+
+    nat->vm->AttachCurrentThread(&env, &args);
+
+    dbus_connection_set_watch_functions(nat->conn, dbusAddWatch,
+            dbusRemoveWatch, dbusToggleWatch, ptr, NULL);
+
+    while (1) {
+        for (int i = 0; i < nat->pollMemberCount; i++) {
+            if (!nat->pollData[i].revents) {
+                continue;
+            }
+            if (nat->pollData[i].fd == nat->controlFdR) {
+                char data;
+                while (recv(nat->controlFdR, &data, sizeof(char), MSG_DONTWAIT)
+                        != -1) {
+                    switch (data) {
+                    case EVENT_LOOP_EXIT:
+                    {
+                        dbus_connection_set_watch_functions(nat->conn,
+                                NULL, NULL, NULL, NULL, NULL);
+                        tearDownEventLoop(nat);
+                        nat->vm->DetachCurrentThread();
+                        shutdown(nat->controlFdR,SHUT_RDWR);
+                        return NULL;
+                    }
+                    case EVENT_LOOP_ADD:
+                    {
+                        handleWatchAdd(nat);
+                        break;
+                    }
+                    case EVENT_LOOP_REMOVE:
+                    {
+                        handleWatchRemove(nat);
+                        break;
+                    }
+                    }
+                }
+            } else {
+                  int event = nat->pollData[i].revents;
+                  int flags = (event & POLLIN ? DBUS_WATCH_READABLE : 0) |
+                              (event & POLLOUT ? DBUS_WATCH_WRITABLE : 0);
+                  dbus_watch_handle(nat->watchData[i], event);
+                  nat->pollData[i].revents = 0;
+                  // can only do one - it may have caused a 'remove'
+                  break;
+            }
+        }
+        while (dbus_connection_dispatch(nat->conn) == 
+                DBUS_DISPATCH_DATA_REMAINS) {
+        }
+
+        poll(nat->pollData, nat->pollMemberCount, -1);
+    }
+}
+#endif // HAVE_BLUETOOTH
+
+static jboolean startEventLoopNative(JNIEnv *env, jobject object) {
+    jboolean result = JNI_FALSE;
+#ifdef HAVE_BLUETOOTH
+    event_loop_native_data_t *nat = get_native_data(env, object);
+
+    pthread_mutex_lock(&(nat->thread_mutex));
+
+    if (nat->pollData) {
+        LOGW("trying to start EventLoop a second time!");
+        pthread_mutex_unlock( &(nat->thread_mutex) );
+        return JNI_FALSE;
+    }
+
+    nat->pollData = (struct pollfd *)malloc(sizeof(struct pollfd) *
+            DEFAULT_INITIAL_POLLFD_COUNT);
+    if (!nat->pollData) {
+        LOGE("out of memory error starting EventLoop!");
+        goto done;
+    }
+
+    nat->watchData = (DBusWatch **)malloc(sizeof(DBusWatch *) *
+            DEFAULT_INITIAL_POLLFD_COUNT);
+    if (!nat->watchData) {
+        LOGE("out of memory error starting EventLoop!");
+        goto done;
+    }
+
+    memset(nat->pollData, 0, sizeof(struct pollfd) *
+            DEFAULT_INITIAL_POLLFD_COUNT);
+    memset(nat->watchData, 0, sizeof(DBusWatch *) *
+            DEFAULT_INITIAL_POLLFD_COUNT);
+    nat->pollDataSize = DEFAULT_INITIAL_POLLFD_COUNT;
+    nat->pollMemberCount = 1;
+
+    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &(nat->controlFdR))) {
+        LOGE("Error getting BT control socket");
+        goto done;
+    }
+    nat->pollData[0].fd = nat->controlFdR;
+    nat->pollData[0].events = POLLIN;
+
+    env->GetJavaVM( &(nat->vm) );
+    nat->envVer = env->GetVersion();
+
+    nat->me = env->NewGlobalRef(object);
+
+    if (setUpEventLoop(nat) != JNI_TRUE) {
+        LOGE("failure setting up Event Loop!");
+        goto done;
+    }
+
+    pthread_create(&(nat->thread), NULL, eventLoopMain, nat);
+    result = JNI_TRUE;
+
+done:
+    if (JNI_FALSE == result) {
+        if (nat->controlFdW || nat->controlFdR) {
+            shutdown(nat->controlFdW, SHUT_RDWR);
+            nat->controlFdW = 0;
+            nat->controlFdR = 0;
+        }
+        if (nat->me) env->DeleteGlobalRef(nat->me);
+        nat->me = NULL;
+        if (nat->pollData) free(nat->pollData);
+        nat->pollData = NULL;
+        if (nat->watchData) free(nat->watchData);
+        nat->watchData = NULL;
+        nat->pollDataSize = 0;
+        nat->pollMemberCount = 0;
+    }
+
+    pthread_mutex_unlock(&(nat->thread_mutex));
+#endif // HAVE_BLUETOOTH
+    return result;
+}
+
+static void stopEventLoopNative(JNIEnv *env, jobject object) {
+#ifdef HAVE_BLUETOOTH
+    native_data_t *nat = get_native_data(env, object);
+
+    pthread_mutex_lock(&(nat->thread_mutex));
+    if (nat->pollData) {
+        char data = EVENT_LOOP_EXIT;
+        ssize_t t = write(nat->controlFdW, &data, sizeof(char));
+        void *ret;
+        pthread_join(nat->thread, &ret);
+
+        env->DeleteGlobalRef(nat->me);
+        nat->me = NULL;
+        free(nat->pollData);
+        nat->pollData = NULL;
+        free(nat->watchData);
+        nat->watchData = NULL;
+        nat->pollDataSize = 0;
+        nat->pollMemberCount = 0;
+        shutdown(nat->controlFdW, SHUT_RDWR);
+        nat->controlFdW = 0;
+        nat->controlFdR = 0;
+    }
+    pthread_mutex_unlock(&(nat->thread_mutex));
+#endif // HAVE_BLUETOOTH
+}
+
+static jboolean isEventLoopRunningNative(JNIEnv *env, jobject object) {
+    jboolean result = JNI_FALSE;
+#ifdef HAVE_BLUETOOTH
+    native_data_t *nat = get_native_data(env, object);
+
+    pthread_mutex_lock(&(nat->thread_mutex));
+    if (nat->pollData) {
+        result = JNI_TRUE;
+    }
+    pthread_mutex_unlock(&(nat->thread_mutex));
+
+#endif // HAVE_BLUETOOTH
+    return result;
 }
 
 #ifdef HAVE_BLUETOOTH
@@ -338,7 +643,7 @@
     dbus_error_init(&err);
 
     nat = (native_data_t *)data;
-    env = nat->env;
+    nat->vm->GetEnv((void**)&env, nat->envVer);
     if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
         LOGV("%s: not interested (not a signal).", __FUNCTION__);
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -556,11 +861,9 @@
 // Called by dbus during WaitForAndDispatchEventNative()
 static DBusHandlerResult agent_event_filter(DBusConnection *conn,
                                             DBusMessage *msg, void *data) {
-    native_data_t *nat = event_loop_nat;
+    native_data_t *nat = (native_data_t *)data;
     JNIEnv *env;
-
-
-    env = nat->env;
+    nat->vm->GetEnv((void**)&env, nat->envVer);
     if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
         LOGV("%s: not interested (not a method call).", __FUNCTION__);
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -730,27 +1033,6 @@
 }
 #endif
 
-static jboolean waitForAndDispatchEventNative(JNIEnv *env, jobject object,
-                                               jint timeout_ms) {
-#ifdef HAVE_BLUETOOTH
-    //LOGV("%s: %8d (pid %d tid %d)",__FUNCTION__, time(NULL), getpid(), gettid()); // too chatty
-    native_data_t *nat = get_native_data(env, object);
-    if (nat != NULL && nat->conn != NULL) {
-        jboolean ret;
-        nat->me = object;
-        nat->env = env;
-        event_loop_nat = nat;
-        ret = dbus_connection_read_write_dispatch_greedy(nat->conn,
-                                                         timeout_ms) == TRUE ?
-              JNI_TRUE : JNI_FALSE;
-        event_loop_nat = NULL;
-        nat->me = NULL;
-        nat->env = NULL;
-        return ret;
-    }
-#endif
-    return JNI_FALSE;
-}
 
 #ifdef HAVE_BLUETOOTH
 //TODO: Unify result codes in a header
@@ -761,13 +1043,16 @@
 #define BOND_RESULT_AUTH_CANCELED 3
 #define BOND_RESULT_REMOTE_DEVICE_DOWN 4
 #define BOND_RESULT_DISCOVERY_IN_PROGRESS 5
-void onCreateBondingResult(DBusMessage *msg, void *user) {
+
+void onCreateBondingResult(DBusMessage *msg, void *user, void *n) {
     LOGV(__FUNCTION__);
 
+    native_data_t *nat = (native_data_t *)n;
     const char *address = (const char *)user;
     DBusError err;
     dbus_error_init(&err);
-    JNIEnv *env = event_loop_nat->env;
+    JNIEnv *env;
+    nat->vm->GetEnv((void**)&env, nat->envVer);
 
     LOGV("... address = %s", address);
 
@@ -809,7 +1094,7 @@
         }
     }
 
-    env->CallVoidMethod(event_loop_nat->me,
+    env->CallVoidMethod(nat->me,
                         method_onCreateBondingResult,
                         env->NewStringUTF(address),
                         result);
@@ -818,13 +1103,17 @@
     free(user);
 }
 
-void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user) {
+void onGetRemoteServiceChannelResult(DBusMessage *msg, void *user, void *n) {
     LOGV(__FUNCTION__);
 
     const char *address = (const char *) user;
+    native_data_t *nat = (native_data_t *) n;
+
     DBusError err;
     dbus_error_init(&err);
-    JNIEnv *env = event_loop_nat->env;
+    JNIEnv *env;
+    nat->vm->GetEnv((void**)&env, nat->envVer);
+
     jint channel = -2;
 
     LOGV("... address = %s", address);
@@ -839,7 +1128,7 @@
     }
 
 done:
-    env->CallVoidMethod(event_loop_nat->me,
+    env->CallVoidMethod(nat->me,
                         method_onGetRemoteServiceChannelResult,
                         env->NewStringUTF(address),
                         channel);
@@ -852,9 +1141,9 @@
     {"classInitNative", "()V", (void *)classInitNative},
     {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative},
     {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative},
-    {"setUpEventLoopNative", "()Z", (void *)setUpEventLoopNative},
-    {"tearDownEventLoopNative", "()V", (void *)tearDownEventLoopNative},
-    {"waitForAndDispatchEventNative", "(I)Z", (void *)waitForAndDispatchEventNative}
+    {"startEventLoopNative", "()V", (void *)startEventLoopNative},
+    {"stopEventLoopNative", "()V", (void *)stopEventLoopNative},
+    {"isEventLoopRunningNative", "()Z", (void *)isEventLoopRunningNative}
 };
 
 int register_android_server_BluetoothEventLoop(JNIEnv *env) {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 3feccde..d760feb 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -50,6 +50,16 @@
 #undef __KERNEL__
 #endif
 
+#define ENABLE_CGROUP_ERR_LOGGING 0
+
+/*
+ * List of cgroup names which map to ANDROID_TGROUP_ values in Thread.h
+ * and Process.java
+ * These names are used to construct the path to the cgroup control dir
+ */
+
+static const char *cgroup_names[] = { NULL, "bg_non_interactive", "fg_boost" };
+
 using namespace android;
 
 static void signalExceptionForPriorityError(JNIEnv* env, jobject obj, int err)
@@ -73,6 +83,28 @@
     }
 }
 
+static void signalExceptionForGroupError(JNIEnv* env, jobject obj, int err)
+{
+    switch (err) {
+        case EINVAL:
+            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+            break;
+        case ESRCH:
+            jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
+            break;
+        case EPERM:
+            jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
+            break;
+        case EACCES:
+            jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group");
+            break;
+        default:
+            jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
+            break;
+    }
+}
+
+
 static void fakeProcessEntry(void* arg)
 {
     String8* cls = (String8*)arg;
@@ -164,9 +196,55 @@
     return -1;
 }
 
+static int add_pid_to_cgroup(int pid, int grp)
+{
+    FILE *fp;
+    char path[255];
+    int rc;
+
+    sprintf(path, "/dev/cpuctl/%s/tasks", (cgroup_names[grp] ? cgroup_names[grp] : ""));
+
+    if (!(fp = fopen(path, "w"))) {
+#if ENABLE_CGROUP_ERR_LOGGING
+        LOGW("Unable to open %s (%s)\n", path, strerror(errno));
+#endif
+        return -errno;
+    }
+
+    rc = fprintf(fp, "%d", pid);
+    fclose(fp);
+
+    if (rc < 0) {
+#if ENABLE_CGROUP_ERR_LOGGING
+        LOGW("Unable to move pid %d to cgroup %s (%s)\n", pid,
+             (cgroup_names[grp] ? cgroup_names[grp] : "<default>"),
+             strerror(errno));
+#endif
+    }
+
+    return (rc < 0) ? errno : 0;
+}
+
+void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
+{
+    if (grp > ANDROID_TGROUP_MAX || grp < 0) { 
+        signalExceptionForGroupError(env, clazz, EINVAL);
+        return;
+    }
+
+    if (add_pid_to_cgroup(pid, grp))
+        signalExceptionForGroupError(env, clazz, errno);
+}
+
 void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
                                               jint pid, jint pri)
 {
+    if (pri == ANDROID_PRIORITY_BACKGROUND) {
+        add_pid_to_cgroup(pid, ANDROID_TGROUP_BG_NONINTERACT);
+    } else if (getpriority(PRIO_PROCESS, pid) == ANDROID_PRIORITY_BACKGROUND) {
+        add_pid_to_cgroup(pid, ANDROID_TGROUP_DEFAULT);
+    }
+
     if (setpriority(PRIO_PROCESS, pid, pri) < 0) {
         signalExceptionForPriorityError(env, clazz, errno);
     }
@@ -516,39 +594,10 @@
     PROC_OUT_FLOAT = 0x4000,
 };
 
-jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz,
-        jstring file, jintArray format, jobjectArray outStrings,
-        jlongArray outLongs, jfloatArray outFloats)
+jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
+        char* buffer, jint startIndex, jint endIndex, jintArray format, 
+        jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
 {
-    if (file == NULL || format == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-        return JNI_FALSE;
-    }
-    
-    const char* file8 = env->GetStringUTFChars(file, NULL);
-    if (file8 == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
-        return JNI_FALSE;
-    }
-    int fd = open(file8, O_RDONLY);
-    env->ReleaseStringUTFChars(file, file8);
-    
-    if (fd < 0) {
-        //LOGW("Unable to open process file: %s\n", file8);
-        return JNI_FALSE;
-    }
-    
-    char buffer[256];
-    const int len = read(fd, buffer, sizeof(buffer)-1);
-    close(fd);
-    
-    if (len < 0) {
-        //LOGW("Unable to open process file: %s fd=%d\n", file8, fd);
-        return JNI_FALSE;
-    }
-    buffer[len] = 0;
-    
-    //LOGI("Process file %s: %s\n", file8, buffer);
     
     const jsize NF = env->GetArrayLength(format);
     const jsize NS = outStrings ? env->GetArrayLength(outStrings) : 0;
@@ -575,7 +624,7 @@
         return JNI_FALSE;
     }
 
-    jsize i = 0;
+    jsize i = startIndex;
     jsize di = 0;
     
     jboolean res = JNI_TRUE;
@@ -587,30 +636,30 @@
         }
         const char term = (char)(mode&PROC_TERM_MASK);
         const jsize start = i;
-        if (i >= len) {
+        if (i >= endIndex) {
             res = JNI_FALSE;
             break;
         }
         
         jsize end = -1;
         if ((mode&PROC_PARENS) != 0) {
-            while (buffer[i] != ')' && i < len) {
+            while (buffer[i] != ')' && i < endIndex) {
                 i++;
             }
             end = i;
             i++;
         }
-        while (buffer[i] != term && i < len) {
+        while (buffer[i] != term && i < endIndex) {
             i++;
         }
         if (end < 0) {
             end = i;
         }
         
-        if (i < len) {
+        if (i < endIndex) {
             i++;
             if ((mode&PROC_COMBINE) != 0) {
-                while (buffer[i] == term && i < len) {
+                while (buffer[i] == term && i < endIndex) {
                     i++;
                 }
             }
@@ -649,6 +698,58 @@
     return res;
 }
 
+jboolean android_os_Process_parseProcLine(JNIEnv* env, jobject clazz,
+        jbyteArray buffer, jint startIndex, jint endIndex, jintArray format, 
+        jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
+{
+        jbyte* bufferArray = env->GetByteArrayElements(buffer, NULL);
+
+        jboolean result = android_os_Process_parseProcLineArray(env, clazz, 
+                (char*) bufferArray, startIndex, endIndex, format, outStrings, 
+                outLongs, outFloats);
+                
+        env->ReleaseByteArrayElements(buffer, bufferArray, 0);
+        
+        return result;
+}
+
+jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz,
+        jstring file, jintArray format, jobjectArray outStrings,
+        jlongArray outLongs, jfloatArray outFloats)
+{
+    if (file == NULL || format == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        return JNI_FALSE;
+    }
+
+    const char* file8 = env->GetStringUTFChars(file, NULL);
+    if (file8 == NULL) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+        return JNI_FALSE;
+    }
+    int fd = open(file8, O_RDONLY);
+    env->ReleaseStringUTFChars(file, file8);
+    
+    if (fd < 0) {
+        //LOGW("Unable to open process file: %s\n", file8);
+        return JNI_FALSE;
+    }
+    
+    char buffer[256];
+    const int len = read(fd, buffer, sizeof(buffer)-1);
+    close(fd);
+    
+    if (len < 0) {
+        //LOGW("Unable to open process file: %s fd=%d\n", file8, fd);
+        return JNI_FALSE;
+    }
+    buffer[len] = 0;
+    
+    return android_os_Process_parseProcLineArray(env, clazz, buffer, 0, len, 
+            format, outStrings, outLongs, outFloats);
+    
+}
+
 void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz,
                                              jobject binderObject)
 {
@@ -718,6 +819,7 @@
     {"setThreadPriority",   "(II)V", (void*)android_os_Process_setThreadPriority},
     {"setThreadPriority",   "(I)V", (void*)android_os_Process_setCallingThreadPriority},
     {"getThreadPriority",   "(I)I", (void*)android_os_Process_getThreadPriority},
+    {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},
     {"setOomAdj",   "(II)Z", (void*)android_os_Process_setOomAdj},
     {"setArgV0",    "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
     {"setUid", "(I)I", (void*)android_os_Process_setUid},
@@ -728,6 +830,7 @@
     {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
     {"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
     {"readProcFile", "(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_readProcFile},
+    {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_parseProcLine},
     {"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
     {"getPss", "(I)J", (void*)android_os_Process_getPss},
     //{"setApplicationObject", "(Landroid/os/IBinder;)V", (void*)android_os_Process_setApplicationObject},
@@ -746,4 +849,3 @@
         env, kProcessPathName,
         methods, NELEM(methods));
 }
-
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 9b09c9b..4ca79b5 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -45,7 +45,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
@@ -1654,6 +1654,7 @@
 #include <string.h>
 
 /* const GLubyte * glGetString ( GLenum name ) */
+static
 jstring
 android_glGetString
   (JNIEnv *_env, jobject _this, jint name) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9f6ebed..caa1318 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -366,6 +366,23 @@
         android:label="@string/permlab_readPhoneState"
         android:description="@string/permdesc_readPhoneState" />
 
+    <!-- ================================== -->
+    <!-- Permissions for sdcard interaction -->
+    <!-- ================================== -->
+    <eat-comment />
+
+    <!-- Group of permissions that are related to SD card access. -->
+    <permission-group android:name="android.permission-group.STORAGE"
+        android:label="@string/permgrouplab_storage"
+        android:description="@string/permgroupdesc_storage" />
+
+    <!-- Allows an application to write to the SD card -->
+    <permission android:name="android.permission.SDCARD_WRITE"
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_sdcardWrite"
+        android:description="@string/permdesc_sdcardWrite"
+        android:protectionLevel="normal" />
+
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
     <!-- ============================================ -->
diff --git a/core/res/res/anim/anticipate_interpolator.xml b/core/res/res/anim/anticipate_interpolator.xml
new file mode 100644
index 0000000..50a555a
--- /dev/null
+++ b/core/res/res/anim/anticipate_interpolator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<anticipateInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/core/res/res/anim/anticipate_overshoot_interpolator.xml b/core/res/res/anim/anticipate_overshoot_interpolator.xml
new file mode 100644
index 0000000..440a899
--- /dev/null
+++ b/core/res/res/anim/anticipate_overshoot_interpolator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<anticipateOvershootInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/core/res/res/anim/bounce_interpolator.xml b/core/res/res/anim/bounce_interpolator.xml
new file mode 100644
index 0000000..406fbb9
--- /dev/null
+++ b/core/res/res/anim/bounce_interpolator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<bounceInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/core/res/res/anim/overshoot_interpolator.xml b/core/res/res/anim/overshoot_interpolator.xml
new file mode 100644
index 0000000..c614e0b
--- /dev/null
+++ b/core/res/res/anim/overshoot_interpolator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/core/res/res/drawable/btn_global_search.xml b/core/res/res/drawable/btn_global_search.xml
new file mode 100644
index 0000000..531f07e
--- /dev/null
+++ b/core/res/res/drawable/btn_global_search.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- TODO Need different assets for some of these button states. -->
+    <item android:state_window_focused="false" android:state_enabled="true"
+        android:drawable="@drawable/btn_global_search_normal" />
+    <item android:state_window_focused="false" android:state_enabled="false"
+        android:drawable="@drawable/btn_global_search_normal" />
+    <item android:state_pressed="true" 
+        android:drawable="@drawable/btn_default_pressed" />
+    <item android:state_focused="true" android:state_enabled="true"
+        android:drawable="@drawable/btn_default_selected" />
+    <item android:state_enabled="true"
+        android:drawable="@drawable/btn_global_search_normal" />
+    <item android:state_focused="true"
+        android:drawable="@drawable/btn_global_search_normal" />
+    <item
+         android:drawable="@drawable/btn_global_search_normal" />
+</selector>
diff --git a/core/res/res/drawable/btn_global_search_normal.9.png b/core/res/res/drawable/btn_global_search_normal.9.png
new file mode 100644
index 0000000..9b7d3e5
--- /dev/null
+++ b/core/res/res/drawable/btn_global_search_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_search_dialog.xml b/core/res/res/drawable/btn_search_dialog.xml
new file mode 100644
index 0000000..b7f5187
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    
+   <item android:state_window_focused="false" android:state_enabled="true"
+        android:drawable="@drawable/btn_search_dialog_default" />
+        
+    <item android:state_pressed="true" 
+        android:drawable="@drawable/btn_search_dialog_pressed" />
+    
+    <item android:state_focused="true" android:state_enabled="true"
+        android:drawable="@drawable/btn_search_dialog_selected" />
+    
+    <item android:state_enabled="true"
+        android:drawable="@drawable/btn_search_dialog_default" />
+    
+    <item
+         android:drawable="@drawable/btn_search_dialog_default" />
+</selector>
diff --git a/core/res/res/drawable/btn_search_dialog_default.9.png b/core/res/res/drawable/btn_search_dialog_default.9.png
new file mode 100644
index 0000000..ec39178
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog_default.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_search_dialog_pressed.9.png b/core/res/res/drawable/btn_search_dialog_pressed.9.png
new file mode 100644
index 0000000..5f52fef
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_search_dialog_selected.9.png b/core/res/res/drawable/btn_search_dialog_selected.9.png
new file mode 100644
index 0000000..9fc2fde
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_search_dialog_voice.xml b/core/res/res/drawable/btn_search_dialog_voice.xml
new file mode 100644
index 0000000..748aaf5
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog_voice.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    
+   <item android:state_window_focused="false" android:state_enabled="true"
+        android:drawable="@drawable/btn_search_dialog_voice_default" />
+        
+    <item android:state_pressed="true" 
+        android:drawable="@drawable/btn_search_dialog_voice_pressed" />
+    
+    <item android:state_focused="true" android:state_enabled="true"
+        android:drawable="@drawable/btn_search_dialog_voice_selected" />
+    
+    <item android:state_enabled="true"
+        android:drawable="@drawable/btn_search_dialog_voice_default" />
+    
+    <item
+         android:drawable="@drawable/btn_search_dialog_voice_default" />
+</selector>
diff --git a/core/res/res/drawable/btn_search_dialog_voice_default.9.png b/core/res/res/drawable/btn_search_dialog_voice_default.9.png
new file mode 100644
index 0000000..2a3366c
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog_voice_default.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_search_dialog_voice_pressed.9.png b/core/res/res/drawable/btn_search_dialog_voice_pressed.9.png
new file mode 100644
index 0000000..57d7a74
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog_voice_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_search_dialog_voice_selected.9.png b/core/res/res/drawable/btn_search_dialog_voice_selected.9.png
new file mode 100644
index 0000000..db3187e
--- /dev/null
+++ b/core/res/res/drawable/btn_search_dialog_voice_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable/search_dropdown_background.9.png b/core/res/res/drawable/search_dropdown_background.9.png
new file mode 100755
index 0000000..a6923b7
--- /dev/null
+++ b/core/res/res/drawable/search_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable/search_plate_global.9.png b/core/res/res/drawable/search_plate_global.9.png
new file mode 100644
index 0000000..1cad902
--- /dev/null
+++ b/core/res/res/drawable/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_connected_1xrtt.png b/core/res/res/drawable/stat_sys_data_connected_1xrtt.png
new file mode 100644
index 0000000..c2fbbdf
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_connected_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_connected_evdo.png b/core/res/res/drawable/stat_sys_data_connected_evdo.png
new file mode 100644
index 0000000..db9f282
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_connected_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_in_1xrtt.png b/core/res/res/drawable/stat_sys_data_in_1xrtt.png
new file mode 100644
index 0000000..a421a8a
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_in_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_in_evdo.png b/core/res/res/drawable/stat_sys_data_in_evdo.png
new file mode 100644
index 0000000..54f55ba
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_in_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_inandout_1xrtt.png b/core/res/res/drawable/stat_sys_data_inandout_1xrtt.png
new file mode 100644
index 0000000..1a94cdf
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_inandout_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_inandout_evdo.png b/core/res/res/drawable/stat_sys_data_inandout_evdo.png
new file mode 100644
index 0000000..7aa6f00
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_inandout_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_out_1xrtt.png b/core/res/res/drawable/stat_sys_data_out_1xrtt.png
new file mode 100644
index 0000000..74fd351
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_out_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_out_evdo.png b/core/res/res/drawable/stat_sys_data_out_evdo.png
new file mode 100644
index 0000000..21e19a7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_out_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable/stat_sys_r_signal_0_cdma.png
new file mode 100644
index 0000000..f615681
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable/stat_sys_r_signal_1_cdma.png
new file mode 100644
index 0000000..c3962a2
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable/stat_sys_r_signal_2_cdma.png
new file mode 100644
index 0000000..68bfe94
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable/stat_sys_r_signal_3_cdma.png
new file mode 100644
index 0000000..4ccd416
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable/stat_sys_r_signal_4_cdma.png
new file mode 100644
index 0000000..0b25570
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_0_cdma.png
new file mode 100644
index 0000000..9a38733
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_1_cdma.png
new file mode 100644
index 0000000..c70e283
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_2_cdma.png
new file mode 100644
index 0000000..a09564c
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_3_cdma.png
new file mode 100644
index 0000000..2637dec
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_4_cdma.png
new file mode 100644
index 0000000..aba13e7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_0_cdma.png b/core/res/res/drawable/stat_sys_signal_0_cdma.png
new file mode 100644
index 0000000..0ef7d53
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_1_cdma.png b/core/res/res/drawable/stat_sys_signal_1_cdma.png
new file mode 100644
index 0000000..f4839d4
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_2_cdma.png b/core/res/res/drawable/stat_sys_signal_2_cdma.png
new file mode 100644
index 0000000..e25a99c
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_3_cdma.png b/core/res/res/drawable/stat_sys_signal_3_cdma.png
new file mode 100644
index 0000000..d828d99
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_4_cdma.png b/core/res/res/drawable/stat_sys_signal_4_cdma.png
new file mode 100644
index 0000000..53a31ea
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_tty_mode.png b/core/res/res/drawable/stat_sys_tty_mode.png
new file mode 100644
index 0000000..ed157a8
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_tty_mode.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_vp_phone_call.png b/core/res/res/drawable/stat_sys_vp_phone_call.png
new file mode 100644
index 0000000..aa03b4f
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_vp_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_vp_phone_call_on_hold.png b/core/res/res/drawable/stat_sys_vp_phone_call_on_hold.png
new file mode 100644
index 0000000..5f45440
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_vp_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/drawable/textfield_search.xml b/core/res/res/drawable/textfield_search.xml
new file mode 100644
index 0000000..2923368
--- /dev/null
+++ b/core/res/res/drawable/textfield_search.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    
+    <item android:state_window_focused="false" android:state_enabled="true"
+        android:drawable="@drawable/textfield_search_default" />
+        
+    <item android:state_pressed="true"
+        android:drawable="@drawable/textfield_search_pressed" />
+        
+    <item android:state_enabled="true" android:state_focused="true"
+        android:drawable="@drawable/textfield_search_selected" />
+    
+    <item android:drawable="@drawable/textfield_search_default" />
+    
+</selector>
+
diff --git a/core/res/res/drawable/textfield_search_default.9.png b/core/res/res/drawable/textfield_search_default.9.png
new file mode 100755
index 0000000..7dc5b27
--- /dev/null
+++ b/core/res/res/drawable/textfield_search_default.9.png
Binary files differ
diff --git a/core/res/res/drawable/textfield_search_pressed.9.png b/core/res/res/drawable/textfield_search_pressed.9.png
new file mode 100644
index 0000000..da00c25
--- /dev/null
+++ b/core/res/res/drawable/textfield_search_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable/textfield_search_selected.9.png b/core/res/res/drawable/textfield_search_selected.9.png
new file mode 100755
index 0000000..a9fd3b2
--- /dev/null
+++ b/core/res/res/drawable/textfield_search_selected.9.png
Binary files differ
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 5e296c5..4c5c456 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -23,7 +23,7 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:layout_height="wrap_content"
     android:layout_width="fill_parent"
-    android:paddingLeft="14dip"
+    android:paddingLeft="10dip"
     android:paddingRight="15dip">
 
     <!-- Activity icon when presenting dialog -->
@@ -42,13 +42,13 @@
             android:textAppearance="?android:attr/textAppearanceLargeInverse"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="6dip" />
+            android:paddingLeft="10dip" />
         <!-- Extended activity info to distinguish between duplicate activity names -->
         <TextView android:id="@android:id/text2"
             android:textAppearance="?android:attr/textAppearanceMediumInverse"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="6dip" />
+            android:paddingLeft="10dip" />
     </LinearLayout>
 </LinearLayout>
 
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index ef347da..5db0737 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -22,83 +22,77 @@
     android:id="@+id/search_bar"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
-    android:paddingBottom="200dip"
-    android:orientation="vertical" 
+    android:orientation="vertical"
     android:focusable="true"
     android:descendantFocusability="afterDescendants">
-    <!-- android:paddingBottom="14dip"  TODO MUST FIX - it's a hack to get the popup to show -->
 
     <!-- Outer layout defines the entire search bar at the top of the screen -->
-    <!-- Bottom padding of 16 is due to the graphic, with 9 extra pixels of drop
-         shadow, plus the desired padding of "8" against the user-visible (grey)
-         pixels, minus "1" to correct for positioning of the edittext & button. -->
     <LinearLayout
         android:id="@+id/search_plate"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:paddingLeft="8dip"
-        android:paddingRight="8dip"
-        android:paddingTop="6dip"
+        android:paddingLeft="12dip"
+        android:paddingRight="12dip"
+        android:paddingTop="7dip"
         android:paddingBottom="16dip"
-        android:baselineAligned="false"
-        android:background="@android:drawable/search_plate"
-        android:addStatesFromChildren="true" >
+        android:background="@drawable/search_plate_global" >
 
         <!-- This is actually used for the badge icon *or* the badge label (or neither) -->
         <TextView 
             android:id="@+id/search_badge"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:paddingLeft="2dip"
+            android:layout_marginBottom="2dip"
             android:drawablePadding="0dip"
             android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorPrimary" />
+            android:textColor="?android:attr/textColorPrimaryInverse" />
 
-        <!-- Inner layout contains the button(s) and EditText -->
-        <!-- The layout_marginTop of "1" corrects for the extra 1 pixel of padding at the top of 
-             textfield_selected.9.png.  The "real" margin as displayed is "2". -->
-        <!-- The layout_marginBottom of "-5" corrects for the spacing we see at the 
-             bottom of the edittext and button images.  The "real" margin as displayed is "8" -->
+        <!-- Inner layout contains the app icon, button(s) and EditText -->
         <LinearLayout
             android:id="@+id/search_edit_frame"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
-            android:layout_marginTop="1dip"
-            android:layout_marginBottom="-5dip"
-            android:orientation="horizontal"
-            android:addStatesFromChildren="true"
-            android:gravity="center_vertical"
-            android:baselineAligned="false" >
+            android:orientation="horizontal">
+            
+            <ImageView
+                android:id="@+id/search_app_icon"
+                android:layout_height="36dip"
+                android:layout_width="36dip"
+                android:layout_marginRight="7dip"
+                android:layout_gravity="center_vertical"
+            />
 
             <view class="android.app.SearchDialog$SearchAutoComplete"
                 android:id="@+id/search_src_text"
+                android:background="@drawable/textfield_search"
                 android:layout_height="wrap_content"
                 android:layout_width="0dip"
                 android:layout_weight="1.0"
                 android:paddingLeft="8dip"
                 android:paddingRight="6dip"
+                android:singleLine="true"
                 android:inputType="text|textAutoComplete"
                 android:dropDownWidth="fill_parent"
                 android:dropDownAnchor="@id/search_plate"
-                android:dropDownVerticalOffset="-15dip"
-                />
-                <!-- android:focusableInTouchMode="false" -->
-                <!-- android:singleLine="true" -->
-                <!-- android:selectAllOnFocus="true" -->
+                android:dropDownVerticalOffset="-9dip"
+                android:popupBackground="@android:drawable/search_dropdown_background"
+            />
                 
             <!-- This button can switch between text and icon "modes" -->
             <Button 
                 android:id="@+id/search_go_btn"
-                android:layout_marginLeft="1dip"
+                android:background="@drawable/btn_search_dialog"
                 android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:drawableLeft="@android:drawable/ic_btn_search"
+                android:layout_height="fill_parent"
             />
 
-            <ImageButton android:id="@+id/search_voice_btn"
+            <ImageButton
+                android:id="@+id/search_voice_btn"
                 android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
+                android:layout_height="fill_parent"
+                android:layout_marginLeft="8dip"
+                android:background="@drawable/btn_search_dialog_voice"
                 android:src="@android:drawable/ic_btn_speak_now"
             />
         </LinearLayout>
diff --git a/core/res/res/layout/search_dropdown_item_1line.xml b/core/res/res/layout/search_dropdown_item_1line.xml
index 3827206..bf3dd48 100644
--- a/core/res/res/layout/search_dropdown_item_1line.xml
+++ b/core/res/res/layout/search_dropdown_item_1line.xml
@@ -20,7 +20,7 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@android:id/text1"
     style="?android:attr/dropDownItemStyle"
-    android:textAppearance="?android:attr/textAppearanceMediumInverse"
+    android:textAppearance="?android:attr/textAppearanceSearchResultTitle"
     android:singleLine="true"
     android:layout_width="fill_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight" />
+    android:layout_height="?android:attr/searchResultListItemHeight" />
\ No newline at end of file
diff --git a/core/res/res/layout/search_dropdown_item_2line.xml b/core/res/res/layout/search_dropdown_item_2line.xml
index 96d6005..5546b6636 100644
--- a/core/res/res/layout/search_dropdown_item_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_2line.xml
@@ -20,15 +20,16 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:layout_height="?android:attr/searchResultListItemHeight"
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:baselineAligned="false"
     >
     
     <TwoLineListItem
-        android:paddingTop="2dip"
-        android:paddingBottom="2dip"
+        android:paddingTop="1dip"
+        android:paddingBottom="1dip"
+        android:gravity="center_vertical"
         android:layout_width="0dip"
         android:layout_weight="1"
         android:layout_height="wrap_content"
@@ -37,7 +38,7 @@
         <TextView
             android:id="@android:id/text1"
             style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceMediumInverse"
+            android:textAppearance="?android:attr/textAppearanceSearchResultTitle"
             android:singleLine="true"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content" />
@@ -45,7 +46,7 @@
         <TextView
             android:id="@android:id/text2"
             style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:textAppearance="?android:attr/textAppearanceSearchResultSubtitle"
             android:textColor="?android:attr/textColorSecondaryInverse"
             android:singleLine="true"
             android:layout_width="fill_parent"
diff --git a/core/res/res/layout/search_dropdown_item_icons_1line.xml b/core/res/res/layout/search_dropdown_item_icons_1line.xml
index c0713d5..4f65d74 100644
--- a/core/res/res/layout/search_dropdown_item_icons_1line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_1line.xml
@@ -22,31 +22,33 @@
     <!-- of the text element in apps/common/res/layout/simple_dropdown_item_1line.xml -->
     
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:paddingLeft="4dip"
+    android:paddingRight="2dip"
     android:layout_width="fill_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:layout_height="?android:attr/searchResultListItemHeight"
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:baselineAligned="false"
     >
     
     <ImageView android:id="@android:id/icon1"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
+        android:layout_width="48dip"
+        android:layout_height="48dip"
         android:layout_gravity="center_vertical"
-        android:scaleType="fitCenter" />
+        android:scaleType="centerInside" />
 
     <TextView android:id="@android:id/text1"
         style="?android:attr/dropDownItemStyle"
-        android:textAppearance="?android:attr/textAppearanceMediumInverse"
+        android:textAppearance="?android:attr/textAppearanceSearchResultTitle"
         android:singleLine="true"
         android:layout_height="wrap_content"
         android:layout_width="0dip"
         android:layout_weight="1"  />
 
     <ImageView android:id="@android:id/icon2"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
+        android:layout_width="48dip"
+        android:layout_height="48dip"
         android:layout_gravity="center_vertical"
-        android:scaleType="fitCenter" />
+        android:scaleType="centerInside" />
 
 </LinearLayout>
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 ad1c905..0d07490 100644
--- a/core/res/res/layout/search_dropdown_item_icons_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/assets/res/any/layout/simple_spinner_item.xml
+/* 
 **
 ** Copyright 2008, The Android Open Source Project
 **
@@ -18,56 +18,62 @@
 */
 -->
 
-    <!-- NOTE: The appearance of the inner text element must match the appearance -->
-    <!-- of the text element in apps/common/res/layout/simple_dropdown_item_2line.xml -->
-    
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:paddingLeft="4dip"
+    android:paddingRight="2dip"
     android:layout_width="fill_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
-    android:orientation="horizontal"
-    android:gravity="center_vertical"
-    android:baselineAligned="false"
-    >
-    
-    <ImageView android:id="@android:id/icon1"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
-        android:layout_gravity="center_vertical"
-        android:scaleType="fitCenter" />
+    android:layout_height="?android:attr/searchResultListItemHeight" >
 
-    <TwoLineListItem
-        android:paddingTop="2dip"
-        android:paddingBottom="2dip"
-        android:layout_width="0dip"
-        android:layout_weight="1"
-        android:layout_height="wrap_content"
-        android:mode="twoLine" >
-    
-        <TextView
-            android:id="@android:id/text1"
-            style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceMediumInverse"
-            android:singleLine="true"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content" />
-    
-        <TextView
-            android:id="@android:id/text2"
-            style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceSmallInverse"
-            android:textColor="?android:attr/textColorSecondaryInverse"
-            android:singleLine="true"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_below="@android:id/text1"
-            android:layout_alignLeft="@android:id/text1" />
-    
-    </TwoLineListItem>
+    <!-- Icons come first in the layout, since their placement doesn't depend on
+         the placement of the text views. -->    
+    <ImageView android:id="@android:id/icon1"
+        android:layout_width="48dip"
+        android:layout_height="48dip"
+        android:scaleType="centerInside"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentBottom="true"
+        android:visibility="gone" />
 
     <ImageView android:id="@android:id/icon2"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
-        android:layout_gravity="center_vertical"
-        android:scaleType="fitCenter" />
+        android:layout_width="48dip"
+        android:layout_height="48dip"
+        android:scaleType="centerInside"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentBottom="true"
+        android:visibility="gone" />
 
-</LinearLayout>
+    <!-- The subtitle comes before the title, since the height of the title depends on whether the
+         subtitle is visible or gone. --> 
+    <TextView android:id="@android:id/text2"
+        style="?android:attr/dropDownItemStyle"
+        android:textAppearance="?android:attr/textAppearanceSearchResultSubtitle"
+        android:singleLine="true"
+        android:layout_width="fill_parent"
+        android:layout_height="29dip" 
+        android:paddingBottom="4dip"
+        android:gravity="top"
+        android:layout_toRightOf="@android:id/icon1"
+        android:layout_toLeftOf="@android:id/icon2"
+        android:layout_alignWithParentIfMissing="true" 
+        android:layout_alignParentBottom="true"
+        android:visibility="gone" />
+    
+    <!-- The title is placed above the subtitle, if there is one. If there is no
+         subtitle, it fills the parent. -->
+    <TextView android:id="@android:id/text1"
+        style="?android:attr/dropDownItemStyle"
+        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_toRightOf="@android:id/icon1"
+        android:layout_toLeftOf="@android:id/icon2"
+        android:layout_above="@android:id/text2"
+        android:layout_alignWithParentIfMissing="true" />
+    
+</RelativeLayout>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 9cfba2e..35a3f9a 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -554,7 +554,7 @@
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"dop."</string>
     <string name="pm">"odp."</string>
-    <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
     <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
     <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -566,7 +566,7 @@
     <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
-    <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
@@ -576,10 +576,10 @@
     <string name="Noon">"Poledne"</string>
     <string name="midnight">"půlnoc"</string>
     <string name="Midnight">"Půlnoc"</string>
-    <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
+    <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for month (7026169712234774086) -->
     <skip />
-    <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
     <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
@@ -597,7 +597,7 @@
     <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
     <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>., <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>., <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>"</string>
     <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
@@ -605,11 +605,11 @@
     <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
     <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
-    <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string>
+    <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"neděle"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f630a11..674c64b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -43,7 +43,7 @@
     <string name="needPuk2">"Geben Sie zum Entsperren der SIM-Karte den PUK2 ein."</string>
     <string name="ClipMmi">"Anrufer-ID für eingehenden Anruf"</string>
     <string name="ClirMmi">"Anrufer-ID für abgehenden Anruf"</string>
-    <string name="CfMmi">"Rufweiterleitung"</string>
+    <string name="CfMmi">"Anrufweiterleitung"</string>
     <string name="CwMmi">"Anklopfen"</string>
     <string name="BaMmi">"Anrufsperre"</string>
     <string name="PwdMmi">"Passwort-Änderung"</string>
@@ -108,9 +108,9 @@
     <string name="global_action_toggle_silent_mode">"Lautlos"</string>
     <string name="global_action_silent_mode_on_status">"Ton ist bereits AUS"</string>
     <string name="global_action_silent_mode_off_status">"Ton ist momentan AN"</string>
-    <string name="global_actions_toggle_airplane_mode">"Flugmodus"</string>
-    <string name="global_actions_airplane_mode_on_status">"Flugmodus ist AN"</string>
-    <string name="global_actions_airplane_mode_off_status">"Flugmodus ist AUS"</string>
+    <string name="global_actions_toggle_airplane_mode">"Flugzeugmodus"</string>
+    <string name="global_actions_airplane_mode_on_status">"Flugzeugmodus ist AN"</string>
+    <string name="global_actions_airplane_mode_off_status">"Flugzeugmodus ist AUS"</string>
     <string name="safeMode">"Abgesicherter Modus"</string>
     <string name="android_system_label">"Android System"</string>
     <string name="permgrouplab_costMoney">"Kostenpflichtige Dienste"</string>
@@ -284,13 +284,13 @@
     <string name="permlab_callPrivileged">"Alle Telefonnummern direkt anrufen"</string>
     <string name="permdesc_callPrivileged">"Ermöglicht der Anwendung, ohne Ihr Eingreifen eine beliebige Telefonnummer zu wählen, einschließlich Notfallnummern. Schädliche Anwendungen können so unnötige und illegale Anrufe an Notdienste tätigen."</string>
     <string name="permlab_locationUpdates">"Benachrichtigungen für Standortaktualisierung steuern"</string>
-    <string name="permdesc_locationUpdates">"Ermöglicht die Aktivierung/Deaktivierung der Mobilfunkbenachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen."</string>
+    <string name="permdesc_locationUpdates">"Ermöglicht die Aktivierung/Deaktivierung der Radio-Benachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen."</string>
     <string name="permlab_checkinProperties">"Auf Check-In-Eigenschaften zugreifen"</string>
     <string name="permdesc_checkinProperties">"Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Anwendungen vorgesehen."</string>
     <string name="permlab_bindGadget">"Widgets auswählen"</string>
     <string name="permdesc_bindGadget">"Ermöglicht der Anwendung, dem System zu melden, welche Widgets von welcher Anwendung verwendet werden können. Mit dieser Berechtigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten gewähren. Nicht für normale Anwendungen vorgesehen."</string>
     <string name="permlab_modifyPhoneState">"Telefonstatus ändern"</string>
-    <string name="permdesc_modifyPhoneState">"Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
+    <string name="permdesc_modifyPhoneState">"Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
     <string name="permlab_readPhoneState">"Telefonstatus lesen"</string>
     <string name="permdesc_readPhoneState">"Ermöglicht der Anwendung, auf die Telefonfunktionen des Gerätes zuzugreifen. Eine Anwendung mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist."</string>
     <string name="permlab_wakeLock">"Standby-Modus deaktivieren"</string>
@@ -388,12 +388,12 @@
   </string-array>
     <string name="keyguard_password_enter_pin_code">"PIN-Code eingeben"</string>
     <string name="keyguard_password_wrong_pin_code">"Falscher PIN-Code!"</string>
-    <string name="keyguard_label_text">"Drücken Sie zum Entsperren die Menütaste und dann auf \"0\"."</string>
+    <string name="keyguard_label_text">"Drücken Sie zum Entsperren auf \"Menü\" und dann auf \"0\"."</string>
     <string name="emergency_call_dialog_number_for_display">"Notrufnummer"</string>
     <string name="lockscreen_carrier_default">"(kein Dienst)"</string>
     <string name="lockscreen_screen_locked">"Display gesperrt."</string>
-    <string name="lockscreen_instructions_when_pattern_enabled">"Drücken Sie die Menütaste, um das Telefon zu entsperren oder einen Notruf zu tätigen."</string>
-    <string name="lockscreen_instructions_when_pattern_disabled">"Zum Entsperren die Menütaste drücken"</string>
+    <string name="lockscreen_instructions_when_pattern_enabled">"Drücken Sie auf \"Menü\", um das Telefon zu entsperren oder einen Notruf zu tätigen."</string>
+    <string name="lockscreen_instructions_when_pattern_disabled">"Drücken Sie zum Entsperren auf \"Menü\"."</string>
     <string name="lockscreen_pattern_instructions">"Schema für Entsperrung zeichnen"</string>
     <string name="lockscreen_emergency_call">"Notruf"</string>
     <string name="lockscreen_pattern_correct">"Korrekt!"</string>
@@ -406,7 +406,7 @@
     <string name="lockscreen_network_locked_message">"Netzwerk gesperrt"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string>
     <string name="lockscreen_sim_puk_locked_instructions">"Weitere Informationen finden Sie in der Bedienungsanleitung oder wenden Sie sich an den Kundendienst."</string>
-    <string name="lockscreen_sim_locked_message">"Bitte PIN-Code eingeben"</string>
+    <string name="lockscreen_sim_locked_message">"SIM-Karte ist gesperrt."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM-Karte wird entsperrt..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. "\n\n"Versuchen Sie es in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden erneut."</string>
     <string name="lockscreen_failed_attempts_almost_glogin">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Telefon mithilfe Ihrer Google-Anmeldeinformationen zu entsperren. "\n\n"Versuchen Sie es in <xliff:g id="NUMBER_2">%d</xliff:g> Sekunden erneut."</string>
@@ -576,7 +576,7 @@
     <string name="Noon">"Mittag"</string>
     <string name="midnight">"Mitternacht"</string>
     <string name="Midnight">"Mitternacht"</string>
-    <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g>"</string>
+    <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
@@ -587,9 +587,9 @@
     <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>,  <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
     <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
-    <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> –  <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
     <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
@@ -609,7 +609,7 @@
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
-    <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g>"</string>
+    <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"Sonntag"</string>
@@ -706,7 +706,7 @@
     <string name="dialog_alert_title">"Achtung"</string>
     <string name="capital_on">"EIN"</string>
     <string name="capital_off">"AUS"</string>
-    <string name="whichApplication">"Aktion durchführen mit"</string>
+    <string name="whichApplication">"Aktion beenden mit"</string>
     <string name="alwaysUse">"Standardmäßig für diese Aktion verwenden."</string>
     <string name="clearDefaultHintMsg">"Löschen Sie die Standardeinstellungen unter \"Starteinstellungen &gt; Anwendungen &gt; Anwendungen verwalten\"."</string>
     <string name="chooseActivity">"Aktion auswählen"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..7b60a39
--- /dev/null
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -0,0 +1,825 @@
+<?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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="byteShort">"B"</string>
+    <string name="kilobyteShort">"KB"</string>
+    <string name="megabyteShort">"MB"</string>
+    <string name="gigabyteShort">"GB"</string>
+    <string name="terabyteShort">"TB"</string>
+    <string name="petabyteShort">"PB"</string>
+    <string name="untitled">"&lt;sin título&gt;"</string>
+    <string name="ellipsis">"…"</string>
+    <string name="emptyPhoneNumber">"(No hay número de teléfono)"</string>
+    <string name="unknownName">"(Desconocida)"</string>
+    <string name="defaultVoiceMailAlphaTag">"Correo de voz"</string>
+    <string name="defaultMsisdnAlphaTag">"MSISDN1"</string>
+    <string name="mmiError">"Problema de conexión o código incorrecto de MMI."</string>
+    <string name="serviceEnabled">"Se ha activado el servicio."</string>
+    <string name="serviceEnabledFor">"Se activó el servicio para:"</string>
+    <string name="serviceDisabled">"Se ha desactivado el servicio."</string>
+    <string name="serviceRegistered">"El registro se ha realizado correctamente."</string>
+    <string name="serviceErased">"Se ha borrado correctamente."</string>
+    <string name="passwordIncorrect">"Contraseña incorrecta."</string>
+    <string name="mmiComplete">"MMI completa."</string>
+    <string name="badPin">"El PIN anterior que escribiste no es correcto."</string>
+    <string name="badPuk">"La PUK que escribiste no es correcta."</string>
+    <string name="mismatchPin">"Los PIN que has ingresado no coinciden."</string>
+    <string name="invalidPin">"Escribir un PIN que contenga entre 4 y 8 números."</string>
+    <string name="needPuk">"Tu tarjeta SIM está bloqueada con PUK. Escribe el código PUK para desbloquearla."</string>
+    <string name="needPuk2">"Escribir PUK2 para desbloquear la tarjeta SIM."</string>
+    <string name="ClipMmi">"Identificador de llamadas entrantes"</string>
+    <string name="ClirMmi">"Identificador de llamadas salientes"</string>
+    <string name="CfMmi">"Desvío de llamadas"</string>
+    <string name="CwMmi">"Llamada en espera"</string>
+    <string name="BaMmi">"Restricción de llamadas"</string>
+    <string name="PwdMmi">"Cambio de contraseña"</string>
+    <string name="PinMmi">"Cambio de PIN"</string>
+    <!-- no translation found for CnipMmi (3110534680557857162) -->
+    <skip />
+    <!-- no translation found for CnirMmi (3062102121430548731) -->
+    <skip />
+    <!-- no translation found for ThreeWCMmi (9051047170321190368) -->
+    <skip />
+    <!-- no translation found for RuacMmi (7827887459138308886) -->
+    <skip />
+    <!-- no translation found for CndMmi (3116446237081575808) -->
+    <skip />
+    <!-- no translation found for DndMmi (1265478932418334331) -->
+    <skip />
+    <string name="CLIRDefaultOnNextCallOn">"El Identificador de llamadas está predeterminado en restringido. Llamada siguiente: restringida"</string>
+    <string name="CLIRDefaultOnNextCallOff">"El Identificador de llamadas está predeterminado en restringido. Llamada siguiente: no restringido"</string>
+    <string name="CLIRDefaultOffNextCallOn">"El Identificador de llamadas está predeterminado en no restringido. Llamada siguiente: restringida"</string>
+    <string name="CLIRDefaultOffNextCallOff">"El Identificador de llamadas está predeterminado en no restringido. Llamada siguiente: no restringido"</string>
+    <string name="serviceNotProvisioned">"Servicio no suministrado."</string>
+    <string name="CLIRPermanent">"La configuración del identificador de llamadas no se puede cambiar."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
+    <string name="serviceClassVoice">"Voz"</string>
+    <string name="serviceClassData">"Datos"</string>
+    <string name="serviceClassFAX">"FAX"</string>
+    <string name="serviceClassSMS">"SMS"</string>
+    <string name="serviceClassDataAsync">"Datos asíncronos"</string>
+    <string name="serviceClassDataSync">"Sincronización"</string>
+    <string name="serviceClassPacket">"Paquete"</string>
+    <string name="serviceClassPAD">"PAD"</string>
+    <string name="cfTemplateNotForwarded">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
+    <string name="cfTemplateForwarded">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
+    <string name="cfTemplateForwardedTime">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> después de <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
+    <string name="cfTemplateRegistered">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
+    <string name="cfTemplateRegisteredTime">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
+    <string name="httpErrorOk">"Aceptar"</string>
+    <string name="httpError">"La página web contiene un error."</string>
+    <string name="httpErrorLookup">"No se ha podido encontrar la URL."</string>
+    <string name="httpErrorUnsupportedAuthScheme">"No se admite el programa de autenticación del sitio."</string>
+    <string name="httpErrorAuth">"La autenticación no se ha realizado correctamente."</string>
+    <string name="httpErrorProxyAuth">"La autenticación a través del servidor proxy no se ha realizado correctamente."</string>
+    <string name="httpErrorConnect">"La conexión al servidor no se ha realizado correctamente."</string>
+    <string name="httpErrorIO">"El servidor no envía comunicaciones. Vuelve a intentarlo más tarde."</string>
+    <string name="httpErrorTimeout">"Se ha agotado el tiempo de espera para la conexión al servidor."</string>
+    <string name="httpErrorRedirectLoop">"La página contiene demasiados redireccionamientos de servidor."</string>
+    <string name="httpErrorUnsupportedScheme">"No se admite el protocolo."</string>
+    <string name="httpErrorFailedSslHandshake">"No se ha podido establecer una conexión segura."</string>
+    <string name="httpErrorBadUrl">"No se ha podido abrir la página debido a que la URL es incorrecta."</string>
+    <string name="httpErrorFile">"No se ha podido acceder al archivo."</string>
+    <string name="httpErrorFileNotFound">"No se ha encontrado el archivo solicitado."</string>
+    <string name="httpErrorTooManyRequests">"Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde."</string>
+    <string name="contentServiceSync">"Sincronización"</string>
+    <string name="contentServiceSyncNotificationTitle">"Sincronización"</string>
+    <string name="contentServiceTooManyDeletesNotificationDesc">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
+    <string name="low_memory">"¡El espacio de almacenamiento está completo! Elimina algunos archivos para liberar espacio."</string>
+    <string name="me">"Yo"</string>
+    <string name="power_dialog">"Opciones de teléfono"</string>
+    <string name="silent_mode">"Modo silencioso"</string>
+    <string name="turn_on_radio">"Encender el teléfono inalámbrico"</string>
+    <string name="turn_off_radio">"Apagar el teléfono inalámbrico"</string>
+    <string name="screen_lock">"Bloqueo de pantalla"</string>
+    <string name="power_off">"Apagar"</string>
+    <string name="shutdown_progress">"Apagando…"</string>
+    <string name="shutdown_confirm">"Tu teléfono se apagará."</string>
+    <string name="no_recent_tasks">"No hay aplicaciones recientes."</string>
+    <string name="global_actions">"Opciones de teléfono"</string>
+    <string name="global_action_lock">"Bloqueo de pantalla"</string>
+    <string name="global_action_power_off">"Apagar"</string>
+    <string name="global_action_toggle_silent_mode">"Modo silencioso"</string>
+    <string name="global_action_silent_mode_on_status">"El sonido está Apagado"</string>
+    <string name="global_action_silent_mode_off_status">"El sonido está Encendido"</string>
+    <string name="global_actions_toggle_airplane_mode">"Modo avión"</string>
+    <string name="global_actions_airplane_mode_on_status">"El modo avión está Encendido"</string>
+    <string name="global_actions_airplane_mode_off_status">"El modo avión está Apagado"</string>
+    <string name="safeMode">"Modo seguro"</string>
+    <string name="android_system_label">"Sistema Androide"</string>
+    <string name="permgrouplab_costMoney">"Servicios que te cuestan dinero"</string>
+    <string name="permgroupdesc_costMoney">"Admite aplicaciones que realizan actividades que te pueden costar dinero."</string>
+    <string name="permgrouplab_messages">"Tus mensajes"</string>
+    <string name="permgroupdesc_messages">"Lee y escribe tu SMS, mensaje de correo electrónico y otros mensajes."</string>
+    <string name="permgrouplab_personalInfo">"Tu información personal"</string>
+    <string name="permgroupdesc_personalInfo">"Acceso directo a tus contactos y calendario guardado en el teléfono."</string>
+    <string name="permgrouplab_location">"Tu ubicación"</string>
+    <string name="permgroupdesc_location">"Controla tu ubicación física"</string>
+    <string name="permgrouplab_network">"Comunicación de red"</string>
+    <string name="permgroupdesc_network">"Admite aplicaciones que acceden a varias funciones de red."</string>
+    <string name="permgrouplab_accounts">"Tus cuentas de Google"</string>
+    <string name="permgroupdesc_accounts">"Acceder a las cuentas disponibles de Google."</string>
+    <string name="permgrouplab_hardwareControls">"Controles de hardware"</string>
+    <string name="permgroupdesc_hardwareControls">"Acceso directo al hardware en el teléfono."</string>
+    <string name="permgrouplab_phoneCalls">"Llamadas telefónicas"</string>
+    <string name="permgroupdesc_phoneCalls">"Controlar, grabar y procesar llamadas telefónicas."</string>
+    <string name="permgrouplab_systemTools">"Herramientas del sistema"</string>
+    <string name="permgroupdesc_systemTools">"Acceso y control de nivel más bajo del sistema."</string>
+    <string name="permgrouplab_developmentTools">"Herramientas de desarrollo"</string>
+    <string name="permgroupdesc_developmentTools">"Las funciones sólo son necesarias para los desarrolladores de aplicaciones."</string>
+    <string name="permlab_statusBar">"desactivar o modificar la barra de estado"</string>
+    <string name="permdesc_statusBar">"Admite que la aplicación desactive la barra de estado, o agregue y elimine íconos del sistema."</string>
+    <string name="permlab_expandStatusBar">"expandir o reducir la barra de estado"</string>
+    <string name="permdesc_expandStatusBar">"Admite que la aplicación expanda o reduzca la barra de estado."</string>
+    <string name="permlab_processOutgoingCalls">"interceptar llamadas salientes"</string>
+    <string name="permdesc_processOutgoingCalls">"Admite que la aplicación procese las llamadas salientes y cambie el número que se debe marcar. Las aplicaciones maliciosas pueden controlar, redireccionar o prevenir llamadas salientes."</string>
+    <string name="permlab_receiveSms">"recibir SMS"</string>
+    <string name="permdesc_receiveSms">"Admite que la aplicación reciba y procese mensajes SMS. Es posible que las aplicaciones maliciosas controlen tus mensajes o los eliminen sin mostrártelos."</string>
+    <string name="permlab_receiveMms">"recibir MMS"</string>
+    <string name="permdesc_receiveMms">"Admite que la aplicación reciba y procese mensajes MMS. Es posible que las aplicaciones maliciosas controlen tus mensajes o los eliminen sin mostrártelos."</string>
+    <string name="permlab_sendSms">"enviar mensajes SMS"</string>
+    <string name="permdesc_sendSms">"Admite que la aplicación envíe mensajes SMS. Las aplicaciones maliciosas te pueden costar dinero si envías mensajes sin su confirmación."</string>
+    <string name="permlab_readSms">"leer SMS o MMS"</string>
+    <string name="permdesc_readSms">"Admite que la aplicación lea los mensajes SMS almacenados en tu teléfono o tarjeta SIM. Las aplicaciones maliciosas pueden leer tus mensajes confidenciales."</string>
+    <string name="permlab_writeSms">"editar SMS o MMS"</string>
+    <string name="permdesc_writeSms">"Admite que la aplicación escriba a los mensajes SMS almacenados en tu teléfono o tarjeta SIM. Las aplicaciones maliciosas pueden borrar tus mensajes."</string>
+    <string name="permlab_receiveWapPush">"recibir WAP"</string>
+    <string name="permdesc_receiveWapPush">"Admite que la aplicación reciba y procese mensajes WAP. Es posible que las aplicaciones maliciosas controlen tus mensajes o los eliminen sin mostrártelos."</string>
+    <string name="permlab_getTasks">"recuperar aplicaciones en ejecución"</string>
+    <string name="permdesc_getTasks">"Admite que la aplicación recupere información sobre tareas en ejecución actuales y recientes. Puede permitir que las aplicaciones maliciosas descubran información privada sobre otras aplicaciones."</string>
+    <string name="permlab_reorderTasks">"reorganizar aplicaciones en ejecución"</string>
+    <string name="permdesc_reorderTasks">"Admite una aplicación que mueve tareas hacia el frente y el fondo. Las aplicaciones maliciosas pueden provocar su propio movimiento hacia el frente sin tu control."</string>
+    <string name="permlab_setDebugApp">"activar la depuración de la aplicación"</string>
+    <string name="permdesc_setDebugApp">"Admite una aplicación que activa la depuración en otra aplicación. Las aplicaciones maliciosas pueden utilizarlo para suprimir otras aplicaciones."</string>
+    <string name="permlab_changeConfiguration">"cambiar tu configuración de la interfaz de usuario"</string>
+    <string name="permdesc_changeConfiguration">"Admite una aplicación para cambiar la configuración actual, como el tamaño de fuente local o general."</string>
+    <string name="permlab_restartPackages">"reiniciar otras aplicaciones"</string>
+    <string name="permdesc_restartPackages">"Admite una aplicación que reinicia otras aplicaciones por la fuerza."</string>
+    <string name="permlab_setProcessForeground">"impedir la detención"</string>
+    <string name="permdesc_setProcessForeground">"Admite una aplicación que ejecuta cualquier tipo de proceso en primer plano, de manera que no se pueda suprimir. Se debe evitar utilizarlo en aplicaciones normales."</string>
+    <string name="permlab_forceBack">"provocar que la aplicación se acerque"</string>
+    <string name="permdesc_forceBack">"Admite una aplicación que provoca que cualquier actividad del fondo se acerque y vuelva a alejarse. Se debe evitar utilizarlo en aplicaciones normales."</string>
+    <string name="permlab_dump">"recuperar el estado interno del sistema"</string>
+    <string name="permdesc_dump">"Admite que la aplicación recupere el estado interno del sistema. Las aplicaciones maliciosas pueden recuperar una gran variedad de información privada y segura que normalmente nunca necesitaría."</string>
+    <string name="permlab_addSystemService">"publicar servicios de bajo nivel"</string>
+    <string name="permdesc_addSystemService">"Admite que la aplicación publique sus propios servicios del sistema de bajo nivel. Las aplicaciones maliciosas pueden apropiarse del sistema y robar o corromper cualquiera de sus datos."</string>
+    <string name="permlab_runSetActivityWatcher">"verificar y controlar todos los lanzamientos de actividades"</string>
+    <string name="permdesc_runSetActivityWatcher">"Admite una aplicación que verifica y controla el lanzamiento de actividades por parte del sistema. Las aplicaciones maliciosas pueden comprometer totalmente al sistema. Este permiso sólo es necesario para el desarrollo, nunca para el uso normal del teléfono."</string>
+    <string name="permlab_broadcastPackageRemoved">"enviar emisión de paquete eliminado"</string>
+    <string name="permdesc_broadcastPackageRemoved">"Admite una aplicación que emite una notificación acerca de que se ha eliminado un paquete de aplicación. Las aplicaciones maliciosas pueden utilizarlo para suprimir cualquier otra aplicación en ejecución."</string>
+    <string name="permlab_broadcastSmsReceived">"enviar emisiones de SMS recibidos"</string>
+    <string name="permdesc_broadcastSmsReceived">"Admite una aplicación que envía una notificación acerca de que se ha recibido un mensaje SMS. Las aplicaciones maliciosas pueden utilizarlo para falsificar los mensajes SMS entrantes."</string>
+    <string name="permlab_broadcastWapPush">"enviar emisiones WAP-PUSH-recibido"</string>
+    <string name="permdesc_broadcastWapPush">"Admite una aplicación que emite una notificación acerca de que se ha recibido un mensaje WAP PUSH. Las aplicaciones maliciosas pueden utilizarlo para falsificar la recepción de mensajes MMS o para reemplazar silenciosamente el contenido de cualquier página web con variantes maliciosas."</string>
+    <string name="permlab_setProcessLimit">"limitar la cantidad de procesos en ejecución"</string>
+    <string name="permdesc_setProcessLimit">"Admite una aplicación que controla la cantidad máxima de procesos que se ejecutarán. No se utiliza nunca en aplicaciones normales."</string>
+    <string name="permlab_setAlwaysFinish">"cerrar todas las aplicaciones del fondo"</string>
+    <string name="permdesc_setAlwaysFinish">"Admite una aplicación que controla si las actividades siempre finalizan cuando van al fondo. No se utiliza nunca en aplicaciones normales."</string>
+    <string name="permlab_fotaUpdate">"instalar automáticamente las actualizaciones del sistema"</string>
+    <string name="permdesc_fotaUpdate">"Admite una aplicación que recibe notificaciones sobre las actualizaciones pendientes del sistema y activa su instalación. Las aplicaciones maliciosas pueden utilizarlo para corromper el sistema con actualizaciones no autorizadas o, en general, para interferir en el proceso de actualización."</string>
+    <string name="permlab_batteryStats">"modificar la estadística de la batería"</string>
+    <string name="permdesc_batteryStats">"Admite la modificación de estadísticas recopiladas sobre la batería. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_internalSystemWindow">"mostrar ventanas no autorizadas"</string>
+    <string name="permdesc_internalSystemWindow">"Permite la creación de ventanas que la interfaz interna del usuario del sistema pretenda utilizar. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_systemAlertWindow">"mostrar alertas a nivel del sistema"</string>
+    <string name="permdesc_systemAlertWindow">"Admite una aplicación que muestra ventanas de alerta del sistema. Las aplicaciones maliciosas pueden tomar el control de toda la pantalla del teléfono."</string>
+    <string name="permlab_setAnimationScale">"modificar la velocidad de la animación global"</string>
+    <string name="permdesc_setAnimationScale">"Admite una aplicación que cambia la velocidad de animación global (animaciones más rápidas o más lentas) en cualquier momento."</string>
+    <string name="permlab_manageAppTokens">"administrar tokens de aplicación"</string>
+    <string name="permdesc_manageAppTokens">"Admite que las aplicaciones creen y administren sus propios tokens y desvíen su curva normal de llenado del espacio. Se debe evitar utilizarlo en aplicaciones normales."</string>
+    <string name="permlab_injectEvents">"presionar teclas y botones de control"</string>
+    <string name="permdesc_injectEvents">"Admite una aplicación que ofrece sus propios eventos de entrada (presionar teclas, etc.) a otras aplicaciones. Las aplicaciones maliciosas pueden utilizarlo para tomar el control del teléfono."</string>
+    <string name="permlab_readInputState">"grabar tu tipo y las medidas que tomes"</string>
+    <string name="permdesc_readInputState">"Admite que las aplicaciones observen las teclas que presionas, incluso al interactuar con otra aplicación (como el ingreso de una contraseña). Se debe evitar utilizarlo en aplicaciones normales."</string>
+    <string name="permlab_bindInputMethod">"vincular a un método de entrada"</string>
+    <string name="permdesc_bindInputMethod">"Permite al propietario vincularse a la interfaz de nivel superior de un método de entrada. Se debe evitar utilizarlo en aplicaciones normales."</string>
+    <string name="permlab_setOrientation">"cambiar la orientación de la pantalla"</string>
+    <string name="permdesc_setOrientation">"Admite una aplicación que cambia la rotación de la pantalla en cualquier momento. Se debe evitar utilizarlo en aplicaciones normales."</string>
+    <string name="permlab_signalPersistentProcesses">"enviar señales de Linux a las aplicaciones"</string>
+    <string name="permdesc_signalPersistentProcesses">"Admite que la aplicación solicite el envío de la señal suministrada a todos los procesos continuos."</string>
+    <string name="permlab_persistentActivity">"hacer que siempre se ejecute la aplicación"</string>
+    <string name="permdesc_persistentActivity">"Admite una aplicación que hace continuas sus propias partes, de modo que el sistema no puede utilizarla para otras aplicaciones."</string>
+    <string name="permlab_deletePackages">"eliminar aplicaciones"</string>
+    <string name="permdesc_deletePackages">"Admite una aplicación que borra paquetes Android. Las aplicaciones maliciosas pueden utilizarlo para eliminar aplicaciones importantes."</string>
+    <string name="permlab_clearAppUserData">"eliminar los datos de otras aplicaciones"</string>
+    <string name="permdesc_clearAppUserData">"Admite una aplicación que borra los datos del usuario."</string>
+    <string name="permlab_deleteCacheFiles">"eliminar las memorias caché de otras aplicaciones"</string>
+    <string name="permdesc_deleteCacheFiles">"Admite una aplicación que borra archivos de memoria caché."</string>
+    <string name="permlab_getPackageSize">"medir el espacio de almacenamiento de la aplicación"</string>
+    <string name="permdesc_getPackageSize">"Admite una aplicación que recupera su código, datos y tamaños de memoria caché"</string>
+    <string name="permlab_installPackages">"instalar aplicaciones directamente"</string>
+    <string name="permdesc_installPackages">"Admite una aplicación que instala paquetes de Android nuevos o actualizados. Las aplicaciones maliciosas pueden utilizarlo para agregar aplicaciones nuevas con permisos arbitrariamente potentes."</string>
+    <string name="permlab_clearAppCache">"eliminar todos los datos de memoria caché de la aplicación"</string>
+    <string name="permdesc_clearAppCache">"Admite una aplicación que libera espacio de almacenamiento en el teléfono al eliminar archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string>
+    <string name="permlab_readLogs">"leer archivos de registro del sistema"</string>
+    <string name="permdesc_readLogs">"Admite una aplicación que lee diversos archivos de registro del sistema. Esto le permite descubrir información general sobre lo que haces con el teléfono, pero no debe contener información personal ni privada."</string>
+    <string name="permlab_diagnostic">"leer y escribir a recursos dentro del grupo de diagnóstico"</string>
+    <string name="permdesc_diagnostic">"Admite una aplicación que lee y escribe a cualquier recurso dentro del grupo de diagnóstico; por ejemplo, archivos con /dev. Esto puede afectar potencialmente la estabilidad y la seguridad del sistema. Debe utilizarlo SÓLO el fabricante o el operador en los diagnósticos específicos del hardware."</string>
+    <string name="permlab_changeComponentState">"activar o desactivar componentes de la aplicación"</string>
+    <string name="permdesc_changeComponentState">"Admite una aplicación que cambia si se debe activar o no un componente de otra aplicación. Las aplicaciones maliciosas pueden utilizarlo para desactivar funciones importantes del teléfono. Se debe tener cuidado con el permiso, ya que es posible que los componentes de la aplicación alcancen un estado inservible, imperfecto e inestable."</string>
+    <string name="permlab_setPreferredApplications">"establecer aplicaciones preferidas"</string>
+    <string name="permdesc_setPreferredApplications">"Admite una aplicación que modifica tus aplicaciones preferidas. Puede admitir aplicaciones maliciosas que cambien silenciosamente las aplicaciones que se ejecutan e imiten tus aplicaciones existentes para recopilar tus datos privados."</string>
+    <string name="permlab_writeSettings">"modificar la configuración global del sistema"</string>
+    <string name="permdesc_writeSettings">"Admite una aplicación que modifica los datos de configuración del sistema. Las aplicaciones maliciosas pueden corromper la configuración de tu sistema."</string>
+    <string name="permlab_writeSecureSettings">"modificar la configuración segura del sistema"</string>
+    <string name="permdesc_writeSecureSettings">"Admite una aplicación que modifica los datos de la configuración segura de los sistemas. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_writeGservices">"modificar el mapa de servicios de Google"</string>
+    <string name="permdesc_writeGservices">"Admite una aplicación que modifica el mapa de servicios de Google. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_receiveBootCompleted">"iniciar automáticamente durante la inicialización"</string>
+    <string name="permdesc_receiveBootCompleted">"Admite una aplicación que se inicia cuando el sistema haya finalizado la inicialización. Esto puede ocasionar que se demore más tiempo en inicializar el teléfono y que la aplicación retarde el funcionamiento total del teléfono al estar en ejecución constante."</string>
+    <string name="permlab_broadcastSticky">"enviar emisiones pegajosas"</string>
+    <string name="permdesc_broadcastSticky">"Admite una aplicación que envía emisiones pegajosas, las cuales permanecen luego de que finaliza la emisión. Las aplicaciones maliciosas pueden hacer lento e inestable al teléfono, ya que ocasiona que utilice demasiada memoria."</string>
+    <string name="permlab_readContacts">"leer datos de contacto"</string>
+    <string name="permdesc_readContacts">"Admite una aplicación que lee todos los datos de (direcciones) de contactos almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
+    <string name="permlab_writeContacts">"escribir datos de contacto"</string>
+    <string name="permdesc_writeContacts">"Admite una aplicación que modifica los datos de (dirección de) contacto guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
+    <string name="permlab_writeOwnerData">"escribir datos del propietario"</string>
+    <string name="permdesc_writeOwnerData">"Admite una aplicación que modifica los datos del propietario del teléfono guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos del propietario."</string>
+    <string name="permlab_readOwnerData">"leer datos del propietario"</string>
+    <string name="permdesc_readOwnerData">"Admite una aplicación que lee los datos del propietario del teléfono guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para leer los datos del propietario del teléfono."</string>
+    <string name="permlab_readCalendar">"leer datos de calendario"</string>
+    <string name="permdesc_readCalendar">"Admite una aplicación que lee todos los eventos de calendario almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
+    <string name="permlab_writeCalendar">"escribir datos de calendario"</string>
+    <string name="permdesc_writeCalendar">"Admite una aplicación que modifica los eventos de calendario guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar tus datos de calendario."</string>
+    <string name="permlab_accessMockLocation">"crear fuentes de ubicación de prueba"</string>
+    <string name="permdesc_accessMockLocation">"Crea fuentes de ubicación de prueba. Las aplicaciones maliciosas pueden utilizarlo para invalidar la ubicación o el estado que arrojen las fuentes de ubicación real, como GPS o proveedores de red."</string>
+    <string name="permlab_accessLocationExtraCommands">"acceder a comandos adicionales del proveedor del lugar"</string>
+    <string name="permdesc_accessLocationExtraCommands">"Accede a comandos adicionales del proveedor del lugar. Las aplicaciones maliciosas pueden utilizarlo para interferir en la operación del GPS u otras fuentes de ubicación."</string>
+    <string name="permlab_accessFineLocation">"ubicación precisa (GPS)"</string>
+    <string name="permdesc_accessFineLocation">"Accede a las fuentes de ubicación precisa, como el Sistema de posicionamiento global en el teléfono, si está disponible. Las aplicaciones maliciosas pueden utilizarlo para determinar donde te encuentras y puede consumir energía adicional de la batería."</string>
+    <string name="permlab_accessCoarseLocation">"ubicación aproximada (basada en la red)"</string>
+    <string name="permdesc_accessCoarseLocation">"Accede a las fuentes de ubicación aproximada, como la base de datos de la red de celulares, para determinar una ubicación telefónica aproximada, si está disponible. Las aplicaciones maliciosas pueden utilizarlo para determinar aproximadamente donde te encuentras."</string>
+    <string name="permlab_accessSurfaceFlinger">"acceder a SurfaceFlinger"</string>
+    <string name="permdesc_accessSurfaceFlinger">"Admite que la aplicación utilice funciones de bajo nivel de SurfaceFlinger."</string>
+    <string name="permlab_readFrameBuffer">"leer el búfer de tramas"</string>
+    <string name="permdesc_readFrameBuffer">"Admite que la aplicación que se utilizará lea el contenido del búfer de tramas."</string>
+    <string name="permlab_modifyAudioSettings">"cambiar tu configuración de audio"</string>
+    <string name="permdesc_modifyAudioSettings">"Admite que la aplicación modifique la configuración global de audio, como el volumen y el enrutamiento."</string>
+    <string name="permlab_recordAudio">"grabar audio"</string>
+    <string name="permdesc_recordAudio">"Admite que la aplicación acceda a la ruta de grabación de audio."</string>
+    <string name="permlab_camera">"tomar fotografías"</string>
+    <string name="permdesc_camera">"Admite una aplicación que toma fotografías con la cámara. Esto permite que la aplicación en cualquier momento recopile imágenes que esté viendo la cámara."</string>
+    <string name="permlab_brick">"desactivar teléfono de manera permanente"</string>
+    <string name="permdesc_brick">"Admite que la aplicación desactive todo el teléfono de manera permanente. Esto es muy peligroso."</string>
+    <string name="permlab_reboot">"provocar el reinicio del teléfono"</string>
+    <string name="permdesc_reboot">"Admite que la aplicación provoque que el teléfono se reinicie."</string>
+    <string name="permlab_mount_unmount_filesystems">"montar y desmontar filesystems"</string>
+    <string name="permdesc_mount_unmount_filesystems">"Admite que la aplicación monte y desmonte filesystems para obtener almacenamiento extraíble."</string>
+    <string name="permlab_mount_format_filesystems">"espacio de almacenamiento externo del formato"</string>
+    <string name="permdesc_mount_format_filesystems">"Admite que la aplicación formatee el espacio de almacenamiento extraíble."</string>
+    <string name="permlab_vibrate">"vibrador de control"</string>
+    <string name="permdesc_vibrate">"Admite que la aplicación controle el vibrador."</string>
+    <string name="permlab_flashlight">"controlar linterna"</string>
+    <string name="permdesc_flashlight">"Admite que la aplicación controle la linterna."</string>
+    <string name="permlab_hardware_test">"probar el hardware"</string>
+    <string name="permdesc_hardware_test">"Admite que la aplicación controle diversos periféricos con el fin de probar el hardware."</string>
+    <string name="permlab_callPhone">"llamar directamente a números de teléfono"</string>
+    <string name="permdesc_callPhone">"Admite que la aplicación llame a ciertos números de teléfono sin tu permiso. Las aplicaciones maliciosas pueden ocasionar llamadas imprevistas en tu factura telefónica. Ten en cuenta que esto no admite que la aplicación llame a los números de emergencia."</string>
+    <string name="permlab_callPrivileged">"llamar directamente a cualquier número de teléfono"</string>
+    <string name="permdesc_callPrivileged">"Admite que la aplicación llame a cualquier número de teléfono, incluidos los números de emergencia, sin tu intervención. Las aplicaciones maliciosas pueden realizar llamadas innecesarias e ilegales a los servicios de emergencia."</string>
+    <string name="permlab_locationUpdates">"controlar las notificaciones de actualización de ubicación"</string>
+    <string name="permdesc_locationUpdates">"Permite activar y desactivar las notificaciones de actualización de ubicación de la radio. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_checkinProperties">"acceder a las propiedades de protección"</string>
+    <string name="permdesc_checkinProperties">"Admite el acceso de lectura y escritura a las propiedades subidas por el servicio de protección. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_bindGadget">"elegir controles"</string>
+    <string name="permdesc_bindGadget">"Admite que la aplicación indique al sistema cuáles controles puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden brindar acceso a los datos personales a otras aplicaciones. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_modifyPhoneState">"modificar el estado del teléfono"</string>
+    <string name="permdesc_modifyPhoneState">"Admite que la aplicación controle las funciones telefónicas del dispositivo. Una aplicación con este permiso puede cambiar las redes, encender y apagar la radio del teléfono y funciones similares sin notificarte en ningún momento."</string>
+    <string name="permlab_readPhoneState">"leer estado del teléfono"</string>
+    <string name="permdesc_readPhoneState">"Admite que la aplicación acceda a las funciones telefónicas del dispositivo. Una aplicación con este permiso puede determinar el número de este teléfono, si una llamada está activa, el número al cual está conectado esa llamada y funciones similares."</string>
+    <string name="permlab_wakeLock">"evitar que el teléfono entre en estado de inactividad"</string>
+    <string name="permdesc_wakeLock">"Admite una aplicación que evita que el teléfono entre en estado de inactividad."</string>
+    <string name="permlab_devicePower">"apagar o encender el teléfono"</string>
+    <string name="permdesc_devicePower">"Admite que la aplicación encienda o apague el teléfono."</string>
+    <string name="permlab_factoryTest">"ejecutar en el modo de prueba de fábrica"</string>
+    <string name="permdesc_factoryTest">"Se ejecuta como una prueba de fábrica de bajo nivel que permite un acceso completo al hardware del teléfono. Sólo disponible cuando un teléfono se ejecuta en el modo de prueba de fábrica."</string>
+    <string name="permlab_setWallpaper">"establecer papel tapiz"</string>
+    <string name="permdesc_setWallpaper">"Admite que la aplicación establezca el papel tapiz del sistema."</string>
+    <string name="permlab_setWallpaperHints">"establecer sugerencias de tamaño del papel tapiz"</string>
+    <string name="permdesc_setWallpaperHints">"Admite que la aplicación establezca las sugerencias de tamaño del papel tapiz del sistema."</string>
+    <string name="permlab_masterClear">"restablecer el sistema a las configuraciones predeterminadas de fábrica"</string>
+    <string name="permdesc_masterClear">"Admite una aplicación que restablece el sistema completamente con su configuración de fábrica, y borra todos los datos, las configuraciones y las aplicaciones instaladas."</string>
+    <string name="permlab_setTimeZone">"establecer zona horaria"</string>
+    <string name="permdesc_setTimeZone">"Admite una aplicación que cambia la zona horaria del teléfono."</string>
+    <string name="permlab_getAccounts">"descubrir cuentas conocidas"</string>
+    <string name="permdesc_getAccounts">"Admite una aplicación que obtiene la lista de cuentas conocidas del teléfono."</string>
+    <string name="permlab_accessNetworkState">"ver estado de la red"</string>
+    <string name="permdesc_accessNetworkState">"Admite una aplicación que ve el estado de todas las redes."</string>
+    <string name="permlab_createNetworkSockets">"acceso total a Internet"</string>
+    <string name="permdesc_createNetworkSockets">"Admite una aplicación que crea conectores de red."</string>
+    <string name="permlab_writeApnSettings">"escribir configuración del Nombre del punto de acceso"</string>
+    <string name="permdesc_writeApnSettings">"Admite una aplicación que modifica la configuración de APN, como el proxy y el puerto de cualquier APN."</string>
+    <string name="permlab_changeNetworkState">"cambiar la conectividad de la red"</string>
+    <string name="permdesc_changeNetworkState">"Admite una aplicación que cambia la conectividad de red del estado."</string>
+    <string name="permlab_changeBackgroundDataSetting">"cambiar la configuración del uso de datos del fondo"</string>
+    <string name="permdesc_changeBackgroundDataSetting">"Admite una aplicación que cambia la configuración del uso de datos del fondo."</string>
+    <string name="permlab_accessWifiState">"ver el estado de Wi-Fi"</string>
+    <string name="permdesc_accessWifiState">"Admite una aplicación que observa la información sobre el estado de Wi-Fi."</string>
+    <string name="permlab_changeWifiState">"cambiar el estado de Wi-Fi"</string>
+    <string name="permdesc_changeWifiState">"Admite una aplicación que se conecta y desconecta de los puntos de acceso de Wi-Fi y que hace cambios en las redes de Wi-Fi configuradas."</string>
+    <string name="permlab_bluetoothAdmin">"administración de bluetooth"</string>
+    <string name="permdesc_bluetoothAdmin">"Admite una aplicación que configura el teléfono Bluetooth local y descubre y se vincula con dispositivos remotos."</string>
+    <string name="permlab_bluetooth">"crear conexiones de Bluetooth"</string>
+    <string name="permdesc_bluetooth">"Admite una aplicación que ve la configuración del teléfono Bluetooth local, y realiza y acepta conexiones con dispositivos vinculados."</string>
+    <string name="permlab_disableKeyguard">"desactivar el bloqueo"</string>
+    <string name="permdesc_disableKeyguard">"Admite una aplicación que desactiva el bloqueo y cualquier seguridad con contraseña relacionada. Un ejemplo legítimo de esto es el bloqueo desactivado por el teléfono cuando recibe una llamada telefónica entrante, y luego la reactivación del bloqueo cuando finaliza la llamada."</string>
+    <string name="permlab_readSyncSettings">"leer la configuración de sincronización"</string>
+    <string name="permdesc_readSyncSettings">"Admite una aplicación que lee la configuración de sincronización, como si está activada la sincronización para los Contactos."</string>
+    <string name="permlab_writeSyncSettings">"escribir configuración de sincronización"</string>
+    <string name="permdesc_writeSyncSettings">"Admite una aplicación que modifica la configuración de sincronización, como si está activada la sincronización para los Contactos."</string>
+    <string name="permlab_readSyncStats">"leer estadística de sincronización"</string>
+    <string name="permdesc_readSyncStats">"Admite una aplicación que lee la estadística de sincronización; por ejemplo, el historial de sincronizaciones que se han producido."</string>
+    <string name="permlab_subscribedFeedsRead">"leer canales suscritos"</string>
+    <string name="permdesc_subscribedFeedsRead">"Admite una aplicación que obtiene detalles sobre los canales actualmente sincronizados."</string>
+    <string name="permlab_subscribedFeedsWrite">"escribir canales suscritos"</string>
+    <string name="permdesc_subscribedFeedsWrite">"Admite una aplicación que modifica tus canales actualmente sincronizados, lo cual podría permitir que una aplicación maliciosa también lo haga."</string>
+    <string name="permlab_readDictionary">"leer diccionario definido por el usuario"</string>
+    <string name="permdesc_readDictionary">"Admite una aplicación para leer palabras, nombres y frases privadas que posiblemente el usuario haya almacenado en el diccionario del usuario."</string>
+    <string name="permlab_writeDictionary">"escribir al diccionario definido por el usuario"</string>
+    <string name="permdesc_writeDictionary">"Admite una aplicación que escribe palabras nuevas en el diccionario del usuario."</string>
+  <string-array name="phoneTypes">
+    <item>"Página principal"</item>
+    <item>"Celular"</item>
+    <item>"Trabajo"</item>
+    <item>"Fax laboral"</item>
+    <item>"Fax residencial"</item>
+    <item>"Localizador"</item>
+    <item>"Otros"</item>
+    <item>"Personalización"</item>
+  </string-array>
+  <string-array name="emailAddressTypes">
+    <item>"Página principal"</item>
+    <item>"Trabajo"</item>
+    <item>"Otros"</item>
+    <item>"Personalización"</item>
+  </string-array>
+  <string-array name="postalAddressTypes">
+    <item>"Página principal"</item>
+    <item>"Trabajo"</item>
+    <item>"Otros"</item>
+    <item>"Personalización"</item>
+  </string-array>
+  <string-array name="imAddressTypes">
+    <item>"Página principal"</item>
+    <item>"Trabajo"</item>
+    <item>"Otros"</item>
+    <item>"Personalización"</item>
+  </string-array>
+  <string-array name="organizationTypes">
+    <item>"Trabajo"</item>
+    <item>"Otros"</item>
+    <item>"Personalización"</item>
+  </string-array>
+  <string-array name="imProtocols">
+    <item>"AIM"</item>
+    <item>"Windows Live"</item>
+    <item>"Yahoo"</item>
+    <item>"Skype"</item>
+    <item>"QQ"</item>
+    <item>"Google Talk"</item>
+    <item>"ICQ"</item>
+    <item>"Jabber"</item>
+  </string-array>
+    <string name="keyguard_password_enter_pin_code">"Ingresar el código de PIN"</string>
+    <string name="keyguard_password_wrong_pin_code">"¡Código de PIN incorrecto!"</string>
+    <string name="keyguard_label_text">"Para desbloquear, presiona el menú y luego 0."</string>
+    <string name="emergency_call_dialog_number_for_display">"Número de emergencia"</string>
+    <string name="lockscreen_carrier_default">"(Sin servicio)"</string>
+    <string name="lockscreen_screen_locked">"Pantalla bloqueada."</string>
+    <string name="lockscreen_instructions_when_pattern_enabled">"Presiona el Menú para desbloquear o realizar una llamada de emergencia."</string>
+    <string name="lockscreen_instructions_when_pattern_disabled">"Presionar Menú para desbloquear."</string>
+    <string name="lockscreen_pattern_instructions">"Extraer el patrón para desbloquear"</string>
+    <string name="lockscreen_emergency_call">"Llamada de emergencia"</string>
+    <string name="lockscreen_pattern_correct">"Correcto"</string>
+    <string name="lockscreen_pattern_wrong">"Lo sentimos, vuelve a intentarlo"</string>
+    <string name="lockscreen_plugged_in">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+    <string name="lockscreen_low_battery">"Conecta tu cargador."</string>
+    <string name="lockscreen_missing_sim_message_short">"No hay tarjeta SIM."</string>
+    <string name="lockscreen_missing_sim_message">"No hay tarjeta SIM en el teléfono."</string>
+    <string name="lockscreen_missing_sim_instructions">"Inserta una tarjeta SIM."</string>
+    <string name="lockscreen_network_locked_message">"Red bloqueada"</string>
+    <string name="lockscreen_sim_puk_locked_message">"La tarjeta SIM está bloqueada con PUK."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
+    <string name="lockscreen_sim_locked_message">"La tarjeta SIM está bloqueada."</string>
+    <string name="lockscreen_sim_unlock_progress_dialog_message">"Desbloqueando tarjeta SIM…"</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message">"Has extraído incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Vuelve a intentarlo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin">"Has extraído incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos, se te solicitará que desbloquees tu teléfono al iniciar sesión en Google. "\n\n" Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="lockscreen_too_many_failed_attempts_countdown">"Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
+    <string name="lockscreen_forgot_pattern_button_text">"¿Olvidaste el patrón?"</string>
+    <string name="lockscreen_glogin_too_many_attempts">"Demasiados intentos de patrón."</string>
+    <string name="lockscreen_glogin_instructions">"Para desbloquear, regístrate en tu cuenta de Google"</string>
+    <string name="lockscreen_glogin_username_hint">"Nombre de usuario (correo electrónico)"</string>
+    <string name="lockscreen_glogin_password_hint">"Contraseña"</string>
+    <string name="lockscreen_glogin_submit_button">"Inicia sesión"</string>
+    <string name="lockscreen_glogin_invalid_input">"Nombre de usuario o contraseña incorrecta."</string>
+    <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
+    <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="status_bar_clear_all_button">"Borrar notificaciones"</string>
+    <string name="status_bar_no_notifications_title">"No hay notificaciones"</string>
+    <string name="status_bar_ongoing_events_title">"Continuo"</string>
+    <string name="status_bar_latest_events_title">"Notificaciones"</string>
+    <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="battery_status_charging">"Cargando..."</string>
+    <string name="battery_low_title">"Conecta el cargador"</string>
+    <string name="battery_low_subtitle">"Hay poca batería:"</string>
+    <string name="battery_low_percent_format">"menos de <xliff:g id="NUMBER">%d%%</xliff:g> restante."</string>
+    <string name="factorytest_failed">"Error en la prueba de fábrica"</string>
+    <string name="factorytest_not_system">"La acción FACTORY_TEST se admite solamente en paquetes instalados en /system/app."</string>
+    <string name="factorytest_no_action">"No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST ."</string>
+    <string name="factorytest_reboot">"Reiniciar"</string>
+    <string name="js_dialog_title">"La página en \"<xliff:g id="TITLE">%s</xliff:g>\" dice:"</string>
+    <string name="js_dialog_title_default">"JavaScript"</string>
+    <string name="js_dialog_before_unload">"¿Deseas salir de esta página?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Selecciona Aceptar para continuar o Cancelar para permanecer en la página actual."</string>
+    <string name="save_password_label">"Confirmar"</string>
+    <string name="save_password_message">"¿Quieres recordar esta contraseña en el navegador?"</string>
+    <string name="save_password_notnow">"Ahora no."</string>
+    <string name="save_password_remember">"Recuerda"</string>
+    <string name="save_password_never">"Nunca"</string>
+    <string name="open_permission_deny">"No dispones de permiso para abrir esta página."</string>
+    <string name="text_copied">"Texto copiado en el portapapeles."</string>
+    <string name="more_item_label">"Más"</string>
+    <string name="prepend_shortcut_label">"Menú+"</string>
+    <string name="menu_space_shortcut_label">"espacio"</string>
+    <string name="menu_enter_shortcut_label">"ingresar"</string>
+    <string name="menu_delete_shortcut_label">"borrar"</string>
+    <string name="search_go">"Buscar"</string>
+    <string name="today">"Hoy"</string>
+    <string name="yesterday">"Ayer"</string>
+    <string name="tomorrow">"Mañana"</string>
+    <string name="oneMonthDurationPast">"hace 1 mes"</string>
+    <string name="beforeOneMonthDurationPast">"Anterior a 1 mes atrás"</string>
+  <plurals name="num_seconds_ago">
+    <item quantity="one">"hace 1 segundo"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="num_minutes_ago">
+    <item quantity="one">"hace 1 minuto"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="num_hours_ago">
+    <item quantity="one">"hace 1 hora"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
+  <plurals name="num_days_ago">
+    <item quantity="one">"ayer"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
+  </plurals>
+  <plurals name="in_num_seconds">
+    <item quantity="one">"en 1 segundo"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="in_num_minutes">
+    <item quantity="one">"en 1 minuto"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="in_num_hours">
+    <item quantity="one">"en 1 hora"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
+  <plurals name="in_num_days">
+    <item quantity="one">"mañana"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> días"</item>
+  </plurals>
+  <plurals name="abbrev_num_seconds_ago">
+    <item quantity="one">"hace 1 segundo"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="abbrev_num_minutes_ago">
+    <item quantity="one">"hace 1 min"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="abbrev_num_hours_ago">
+    <item quantity="one">"hace 1 hora"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
+  <plurals name="abbrev_num_days_ago">
+    <item quantity="one">"ayer"</item>
+    <item quantity="other">"hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
+  </plurals>
+  <plurals name="abbrev_in_num_seconds">
+    <item quantity="one">"en 1 segundo"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+  <plurals name="abbrev_in_num_minutes">
+    <item quantity="one">"en 1 minuto"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+  <plurals name="abbrev_in_num_hours">
+    <item quantity="one">"en 1 hora"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
+  <plurals name="abbrev_in_num_days">
+    <item quantity="one">"mañana"</item>
+    <item quantity="other">"en <xliff:g id="COUNT">%d</xliff:g> días"</item>
+  </plurals>
+    <string name="preposition_for_date">"en %s"</string>
+    <string name="preposition_for_time">"en %s"</string>
+    <string name="preposition_for_year">"en %s"</string>
+    <string name="day">"día"</string>
+    <string name="days">"días"</string>
+    <string name="hour">"hora"</string>
+    <string name="hours">"horas"</string>
+    <string name="minute">"min"</string>
+    <string name="minutes">"mins"</string>
+    <string name="second">"segundo"</string>
+    <string name="seconds">"segundos"</string>
+    <string name="week">"semana"</string>
+    <string name="weeks">"semanas"</string>
+    <string name="year">"año"</string>
+    <string name="years">"años"</string>
+    <string name="sunday">"Domingo"</string>
+    <string name="monday">"Lunes"</string>
+    <string name="tuesday">"Martes"</string>
+    <string name="wednesday">"Miércoles"</string>
+    <string name="thursday">"Jueves"</string>
+    <string name="friday">"Viernes"</string>
+    <string name="saturday">"Sábado"</string>
+    <string name="every_weekday">"Los días de semana (lunes a viernes)"</string>
+    <string name="daily">"Diariamente"</string>
+    <string name="weekly">"Semanalmente el día <xliff:g id="DAY">%s</xliff:g>"</string>
+    <string name="monthly">"Mensual"</string>
+    <string name="yearly">"Anual"</string>
+    <string name="VideoView_error_title">"No se puede reproducir el video"</string>
+    <string name="VideoView_error_text_invalid_progressive_playback">"Lo sentimos, este video no es válido para las transmisiones a este dispositivo."</string>
+    <string name="VideoView_error_text_unknown">"Lo sentimos, no se puede reproducir este video."</string>
+    <string name="VideoView_error_button">"Aceptar"</string>
+    <string name="am">"AM"</string>
+    <string name="pm">"PM"</string>
+    <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
+    <string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
+    <string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
+    <string name="date1_date2">"<xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>"</string>
+    <string name="time1_time2">"<xliff:g id="TIME1">%1$s</xliff:g> – <xliff:g id="TIME2">%2$s</xliff:g>"</string>
+    <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string>
+    <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string>
+    <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string>
+    <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
+    <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="noon">"mediodía"</string>
+    <string name="Noon">"Mediodía"</string>
+    <string name="midnight">"medianoche"</string>
+    <string name="Midnight">"Medianoche"</string>
+    <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
+    <!-- no translation found for month (7026169712234774086) -->
+    <skip />
+    <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
+    <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
+    <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
+    <string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
+    <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string>
+    <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
+    <string name="numeric_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>"</string>
+    <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
+    <string name="same_month_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="abbrev_month_day_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
+    <skip />
+    <string name="day_of_week_long_sunday">"Domingo"</string>
+    <string name="day_of_week_long_monday">"Lunes"</string>
+    <string name="day_of_week_long_tuesday">"Martes"</string>
+    <string name="day_of_week_long_wednesday">"Miércoles"</string>
+    <string name="day_of_week_long_thursday">"Jueves"</string>
+    <string name="day_of_week_long_friday">"Viernes"</string>
+    <string name="day_of_week_long_saturday">"Sábado"</string>
+    <string name="day_of_week_medium_sunday">"Dom."</string>
+    <string name="day_of_week_medium_monday">"Lun."</string>
+    <string name="day_of_week_medium_tuesday">"Mar."</string>
+    <string name="day_of_week_medium_wednesday">"Mié."</string>
+    <string name="day_of_week_medium_thursday">"Jue."</string>
+    <string name="day_of_week_medium_friday">"Vie."</string>
+    <string name="day_of_week_medium_saturday">"Sáb."</string>
+    <string name="day_of_week_short_sunday">"Dom."</string>
+    <string name="day_of_week_short_monday">"Lun."</string>
+    <string name="day_of_week_short_tuesday">"Mar."</string>
+    <string name="day_of_week_short_wednesday">"Nosotros"</string>
+    <string name="day_of_week_short_thursday">"Jue."</string>
+    <string name="day_of_week_short_friday">"V"</string>
+    <string name="day_of_week_short_saturday">"Sáb."</string>
+    <string name="day_of_week_shorter_sunday">"Dom."</string>
+    <string name="day_of_week_shorter_monday">"L"</string>
+    <string name="day_of_week_shorter_tuesday">"Mar."</string>
+    <string name="day_of_week_shorter_wednesday">"M"</string>
+    <string name="day_of_week_shorter_thursday">"Jue."</string>
+    <string name="day_of_week_shorter_friday">"V"</string>
+    <string name="day_of_week_shorter_saturday">"Sáb."</string>
+    <string name="day_of_week_shortest_sunday">"D"</string>
+    <string name="day_of_week_shortest_monday">"L"</string>
+    <string name="day_of_week_shortest_tuesday">"Mar."</string>
+    <string name="day_of_week_shortest_wednesday">"M"</string>
+    <string name="day_of_week_shortest_thursday">"Jue."</string>
+    <string name="day_of_week_shortest_friday">"V"</string>
+    <string name="day_of_week_shortest_saturday">"D"</string>
+    <string name="month_long_january">"Enero"</string>
+    <string name="month_long_february">"Febrero"</string>
+    <string name="month_long_march">"Marzo"</string>
+    <string name="month_long_april">"Abril"</string>
+    <string name="month_long_may">"Mayo"</string>
+    <string name="month_long_june">"Junio"</string>
+    <string name="month_long_july">"Julio"</string>
+    <string name="month_long_august">"Agosto"</string>
+    <string name="month_long_september">"Septiembre"</string>
+    <string name="month_long_october">"Octubre"</string>
+    <string name="month_long_november">"Noviembre"</string>
+    <string name="month_long_december">"Diciembre"</string>
+    <string name="month_medium_january">"Ene."</string>
+    <string name="month_medium_february">"Feb."</string>
+    <string name="month_medium_march">"Mar."</string>
+    <string name="month_medium_april">"Abr."</string>
+    <string name="month_medium_may">"Mayo"</string>
+    <string name="month_medium_june">"Jun."</string>
+    <string name="month_medium_july">"Jul."</string>
+    <string name="month_medium_august">"Ago."</string>
+    <string name="month_medium_september">"Sep."</string>
+    <string name="month_medium_october">"Oct."</string>
+    <string name="month_medium_november">"Nov."</string>
+    <string name="month_medium_december">"Dic."</string>
+    <string name="month_shortest_january">"E"</string>
+    <string name="month_shortest_february">"V"</string>
+    <string name="month_shortest_march">"M"</string>
+    <string name="month_shortest_april">"A"</string>
+    <string name="month_shortest_may">"M"</string>
+    <string name="month_shortest_june">"E"</string>
+    <string name="month_shortest_july">"J"</string>
+    <string name="month_shortest_august">"Ago."</string>
+    <string name="month_shortest_september">"D"</string>
+    <string name="month_shortest_october">"O"</string>
+    <string name="month_shortest_november">"N"</string>
+    <string name="month_shortest_december">"Dic."</string>
+    <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
+    <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
+    <string name="selectAll">"Seleccionar todos"</string>
+    <string name="selectText">"Seleccionar texto"</string>
+    <string name="stopSelectingText">"Detener la selección de texto"</string>
+    <string name="cut">"Cortar"</string>
+    <string name="cutAll">"Cortar llamada"</string>
+    <string name="copy">"Copiar"</string>
+    <string name="copyAll">"Copiar todo"</string>
+    <string name="paste">"Pegar"</string>
+    <string name="copyUrl">"Copiar URL"</string>
+    <string name="inputMethod">"Método de entrada"</string>
+    <string name="addToDictionary">"Agregar \"%s\" al diccionario"</string>
+    <string name="editTextMenuTitle">"Editar texto"</string>
+    <string name="low_internal_storage_view_title">"Poco espacio de almacenamiento"</string>
+    <string name="low_internal_storage_view_text">"Hay poco espacio de almacenamiento en el teléfono."</string>
+    <string name="ok">"Aceptar"</string>
+    <string name="cancel">"Cancelar"</string>
+    <string name="yes">"Aceptar"</string>
+    <string name="no">"Cancelar"</string>
+    <string name="dialog_alert_title">"Atención"</string>
+    <string name="capital_on">"Encendido"</string>
+    <string name="capital_off">"APAGADO"</string>
+    <string name="whichApplication">"Completar la acción mediante"</string>
+    <string name="alwaysUse">"Utilizar de manera predeterminada en esta acción."</string>
+    <string name="clearDefaultHintMsg">"Borrar la predeterminación en Configuración de la página principal &gt; Aplicaciones &gt; Administrar aplicaciones."</string>
+    <string name="chooseActivity">"Seleccionar una acción"</string>
+    <string name="noApplications">"Ninguna aplicación puede realizar esta acción."</string>
+    <string name="aerr_title">"¡Lo sentimos!"</string>
+    <string name="aerr_application">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) se ha detenido de forma imprevista. Vuelve a intentarlo."</string>
+    <string name="aerr_process">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> se ha detenido de forma imprevista. Vuelve a intentarlo."</string>
+    <string name="anr_title">"¡Lo sentimos!"</string>
+    <string name="anr_activity_application">"La actividad <xliff:g id="ACTIVITY">%1$s</xliff:g> (en la aplicación <xliff:g id="APPLICATION">%2$s</xliff:g>) no responde."</string>
+    <string name="anr_activity_process">"La actividad <xliff:g id="ACTIVITY">%1$s</xliff:g> (en proceso <xliff:g id="PROCESS">%2$s</xliff:g>) no responde."</string>
+    <string name="anr_application_process">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (en proceso <xliff:g id="PROCESS">%2$s</xliff:g>) no responde."</string>
+    <string name="anr_process">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> no responde."</string>
+    <string name="force_close">"Provocar acercamiento"</string>
+    <string name="wait">"Espera"</string>
+    <string name="debug">"Depurar"</string>
+    <string name="sendText">"Selecciona una acción para el texto"</string>
+    <string name="volume_ringtone">"Volumen del timbre"</string>
+    <string name="volume_music">"Volumen de los medios"</string>
+    <string name="volume_music_hint_playing_through_bluetooth">"Reproduciendo a través de Bluetooth"</string>
+    <string name="volume_call">"Volumen de llamadas entrantes"</string>
+    <string name="volume_bluetooth_call">"Volumen en llamada de Bluetooth"</string>
+    <string name="volume_alarm">"Volumen de la alarma"</string>
+    <string name="volume_notification">"Volumen de notificación"</string>
+    <string name="volume_unknown">"Volumen"</string>
+    <string name="ringtone_default">"Tono de llamada predeterminado"</string>
+    <string name="ringtone_default_with_actual">"Tono de llamada predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_silent">"Silencioso"</string>
+    <string name="ringtone_picker_title">"Tonos de llamada"</string>
+    <string name="ringtone_unknown">"Tono de llamada desconocido"</string>
+  <plurals name="wifi_available">
+    <item quantity="one">"Red disponible de Wi-Fi"</item>
+    <item quantity="other">"redes disponibles de Wi-Fi"</item>
+  </plurals>
+  <plurals name="wifi_available_detailed">
+    <item quantity="one">"Abrir red disponible de Wi-Fi"</item>
+    <item quantity="other">"Abrir redes disponibles de Wi-Fi"</item>
+  </plurals>
+    <string name="select_character">"Insertar caracteres"</string>
+    <string name="sms_control_default_app_name">"Aplicación desconocida"</string>
+    <string name="sms_control_title">"Enviando mensajes SMS"</string>
+    <string name="sms_control_message">"Se envía una gran cantidad de mensajes SMS. Selecciona \"Aceptar\" para continuar o \"Cancelar\" para detener el envío."</string>
+    <string name="sms_control_yes">"Aceptar"</string>
+    <string name="sms_control_no">"Cancelar"</string>
+    <string name="date_time_set">"Establecer"</string>
+    <string name="default_permission_group">"Predeterminado"</string>
+    <string name="no_permissions">"No se requieren permisos"</string>
+    <string name="perms_hide"><b>"Ocultar"</b></string>
+    <string name="perms_show_all"><b>"Mostrar todos"</b></string>
+    <string name="googlewebcontenthelper_loading">"Cargando…"</string>
+    <string name="usb_storage_title">"conectado al USB"</string>
+    <string name="usb_storage_message">"Has conectado tu teléfono a tu computadora a través de USB. Selecciona \"Montar\" si deseas copiar archivos entre tu computadora y la tarjeta SD de tu teléfono."</string>
+    <string name="usb_storage_button_mount">"Montar"</string>
+    <string name="usb_storage_button_unmount">"No montar"</string>
+    <string name="usb_storage_error_message">"Hay un problema para utilizar tu tarjeta SD en el almacenamiento USB."</string>
+    <string name="usb_storage_notification_title">"conectado al USB"</string>
+    <string name="usb_storage_notification_message">"Seleccionar para copiar archivos desde o hacia tu computadora."</string>
+    <string name="usb_storage_stop_notification_title">"Apagar el almacenamiento USB"</string>
+    <string name="usb_storage_stop_notification_message">"Seleccionar para desactivar el almacenamiento USB."</string>
+    <string name="usb_storage_stop_title">"Apagar el almacenamiento USB"</string>
+    <string name="usb_storage_stop_message">"Antes de desactivar el almacenamiento USB, asegúrate de haberlo desmontado en el servidor USB al seleccionar \"Desactivar\"."</string>
+    <string name="usb_storage_stop_button_mount">"Apagar"</string>
+    <string name="usb_storage_stop_button_unmount">"Cancelar"</string>
+    <string name="usb_storage_stop_error_message">"Se ha producido un problema al desactivar el almacenamiento USB. Verifica para asegurarte de haber desmontado el servidor USB, luego vuelve a intentarlo."</string>
+    <string name="extmedia_format_title">"Formatear tarjeta SD"</string>
+    <string name="extmedia_format_message">"¿Estás seguro de que quieres formatear la tarjeta SD? Se perderán todos los datos de tu tarjeta."</string>
+    <string name="extmedia_format_button_format">"Formato"</string>
+    <string name="select_input_method">"Seleccionar método de entrada"</string>
+    <string name="fast_scroll_alphabet">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="fast_scroll_numeric_alphabet">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <string name="candidates_style"><u>"candidatos"</u></string>
+    <string name="ext_media_checking_notification_title">"Preparación de la tarjeta SD"</string>
+    <string name="ext_media_checking_notification_message">"Verificando errores"</string>
+    <string name="ext_media_nofs_notification_title">"Tarjeta SD vacía"</string>
+    <string name="ext_media_nofs_notification_message">"La tarjeta SD está vacía o utiliza un filesystem no admitido."</string>
+    <string name="ext_media_unmountable_notification_title">"Tarjeta SD dañada"</string>
+    <string name="ext_media_unmountable_notification_message">"La tarjeta SD está dañada. Es posible que debas reformatear tu tarjeta."</string>
+    <string name="ext_media_badremoval_notification_title">"Tarjeta SD extraída de forma imprevista"</string>
+    <string name="ext_media_badremoval_notification_message">"Desmontar la tarjeta SD antes de extraerla para evitar la pérdida de datos."</string>
+    <string name="ext_media_safe_unmount_notification_title">"Tarjeta SD fácil de extraer"</string>
+    <string name="ext_media_safe_unmount_notification_message">"La tarjeta SD ahora se puede extraer de manera segura."</string>
+    <string name="ext_media_nomedia_notification_title">"Tarjeta SD extraída"</string>
+    <string name="ext_media_nomedia_notification_message">"Se ha extraído la SD. Inserta una nueva tarjeta SD para aumentar el espacio de almacenamiento de tu dispositivo."</string>
+    <string name="activity_list_empty">"No se encontraron actividades coincidentes"</string>
+    <string name="permlab_pkgUsageStats">"actualizar la estadística de uso de los componentes"</string>
+    <string name="permdesc_pkgUsageStats">"Permite la modificación de estadísticas recopiladas sobre el uso de componentes. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="tutorial_double_tap_to_zoom_message_short">"Presiona dos veces para obtener el control del zoom"</string>
+    <string name="gadget_host_error_inflating">"Error al aumentar el control"</string>
+    <string name="ime_action_go">"Ir"</string>
+    <string name="ime_action_search">"Buscar"</string>
+    <string name="ime_action_send">"Enviar"</string>
+    <string name="ime_action_next">"Siguiente"</string>
+    <string name="ime_action_done">"Finalizado"</string>
+    <string name="ime_action_default">"Ejecutar"</string>
+    <!-- no translation found for dial_number_using (5789176425167573586) -->
+    <skip />
+    <!-- no translation found for create_contact_using (4947405226788104538) -->
+    <skip />
+</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index cf1811b..a9f267a 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -53,7 +53,7 @@
     <string name="CLIRDefaultOffNextCallOn">"El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: Restringido"</string>
     <string name="CLIRDefaultOffNextCallOff">"El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: No restringido"</string>
     <string name="serviceNotProvisioned">"El servicio no se suministra."</string>
-    <string name="CLIRPermanent">"El ID de emisor no se puede modificar."</string>
+    <string name="CLIRPermanent">"El ID del emisor no se puede modificar."</string>
     <string name="RestrictedChangedTitle">"El acceso restringido se ha modificado."</string>
     <string name="RestrictedOnData">"El servicio de datos está bloqueado."</string>
     <string name="RestrictedOnEmergency">"El servicio de emergencia está bloqueado."</string>
@@ -109,8 +109,8 @@
     <string name="global_action_silent_mode_on_status">"El sonido está desactivado. Activar."</string>
     <string name="global_action_silent_mode_off_status">"El sonido está activado. Desactivar."</string>
     <string name="global_actions_toggle_airplane_mode">"Modo avión"</string>
-    <string name="global_actions_airplane_mode_on_status">"Modo avión desactivado. Activar."</string>
-    <string name="global_actions_airplane_mode_off_status">"Modo avión desactivado. Activar."</string>
+    <string name="global_actions_airplane_mode_on_status">"Modo avión ACTIVADO"</string>
+    <string name="global_actions_airplane_mode_off_status">"Modo avión DESACTIVADO"</string>
     <string name="safeMode">"Modo seguro"</string>
     <string name="android_system_label">"Sistema Android"</string>
     <string name="permgrouplab_costMoney">"Servicios por los que tienes que pagar"</string>
@@ -406,7 +406,7 @@
     <string name="lockscreen_network_locked_message">"Bloqueada para la red"</string>
     <string name="lockscreen_sim_puk_locked_message">"La tarjeta SIM está bloqueada con el código PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions">"Consulta la guía del usuario o ponte en contacto con el servicio de atención al cliente."</string>
-    <string name="lockscreen_sim_locked_message">"Introduce el código PIN."</string>
+    <string name="lockscreen_sim_locked_message">"La tarjeta SIM está bloqueada."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Desbloqueando tarjeta SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación de un patrón de desbloqueo. "\n\n"Inténtalo de nuevo dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
     <string name="lockscreen_failed_attempts_almost_glogin">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación del patrón de desbloqueo. Si realizas <xliff:g id="NUMBER_1">%d</xliff:g> intentos fallidos más, se te pedirá que desbloquees el teléfono con tus credenciales de acceso de Google."\n\n" Espera <xliff:g id="NUMBER_2">%d</xliff:g> segundos e inténtalo de nuevo."</string>
@@ -419,10 +419,10 @@
     <string name="lockscreen_glogin_submit_button">"Acceder"</string>
     <string name="lockscreen_glogin_invalid_input">"Nombre de usuario o contraseña no válido"</string>
     <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
-    <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
-    <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="status_bar_clear_all_button">"Cerrar notificaciones"</string>
     <string name="status_bar_no_notifications_title">"No tienes notificaciones"</string>
     <string name="status_bar_ongoing_events_title">"Entrante"</string>
@@ -536,13 +536,13 @@
     <string name="weeks">"semanas"</string>
     <string name="year">"año"</string>
     <string name="years">"años"</string>
-    <string name="sunday">"domingo"</string>
-    <string name="monday">"lunes"</string>
-    <string name="tuesday">"martes"</string>
-    <string name="wednesday">"miércoles"</string>
-    <string name="thursday">"jueves"</string>
-    <string name="friday">"viernes"</string>
-    <string name="saturday">"sábado"</string>
+    <string name="sunday">"Domingo"</string>
+    <string name="monday">"Lunes"</string>
+    <string name="tuesday">"Martes"</string>
+    <string name="wednesday">"Miércoles"</string>
+    <string name="thursday">"Jueves"</string>
+    <string name="friday">"Viernes"</string>
+    <string name="saturday">"Sábado"</string>
     <string name="every_weekday">"Todos los días laborables (Lun-Vie)"</string>
     <string name="daily">"Diariamente"</string>
     <string name="weekly">"Semanalmente, el <xliff:g id="DAY">%s</xliff:g>"</string>
@@ -569,30 +569,30 @@
     <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
     <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"mediodía"</string>
     <string name="Noon">"Mediodía"</string>
     <string name="midnight">"medianoche"</string>
     <string name="Midnight">"Medianoche"</string>
-    <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> de <xliff:g id="MONTH">%B</xliff:g>"</string>
+    <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
     <!-- no translation found for month (7026169712234774086) -->
     <skip />
-    <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> de <xliff:g id="MONTH">%B</xliff:g> de <xliff:g id="YEAR">%Y</xliff:g>"</string>
-    <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> de <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
-    <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>, <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
     <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
     <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>,  <xliff:g id="DAY2_1">%8$s</xliff:g>  <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
     <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> de <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> de <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>  <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>  <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>,  <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> de <xliff:g id="MONTH1">%2$s</xliff:g> de <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> –  <xliff:g id="DAY2">%8$s</xliff:g> de <xliff:g id="MONTH2">%7$s</xliff:g> de <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
-    <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
+    <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
     <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
     <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
@@ -600,31 +600,31 @@
     <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>  <xliff:g id="MONTH1">%2$s</xliff:g>"</string>
-    <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>  <xliff:g id="MONTH1">%2$s</xliff:g>  – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>  <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
+    <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
     <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>  <xliff:g id="MONTH1">%2$s</xliff:g>,  <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>  <xliff:g id="MONTH2">%7$s</xliff:g>,  <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> de <xliff:g id="MONTH1">%2$s</xliff:g> de <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> de <xliff:g id="MONTH2">%7$s</xliff:g> de <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
     <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>  <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>  <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> de <xliff:g id="MONTH">%b</xliff:g> de <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
-    <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g>  <xliff:g id="MONTH">%b</xliff:g>"</string>
+    <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
-    <string name="day_of_week_long_sunday">"domingo"</string>
-    <string name="day_of_week_long_monday">"lunes"</string>
-    <string name="day_of_week_long_tuesday">"martes"</string>
-    <string name="day_of_week_long_wednesday">"miércoles"</string>
-    <string name="day_of_week_long_thursday">"jueves"</string>
-    <string name="day_of_week_long_friday">"viernes"</string>
-    <string name="day_of_week_long_saturday">"sábado"</string>
+    <string name="day_of_week_long_sunday">"Domingo"</string>
+    <string name="day_of_week_long_monday">"Lunes"</string>
+    <string name="day_of_week_long_tuesday">"Martes"</string>
+    <string name="day_of_week_long_wednesday">"Miércoles"</string>
+    <string name="day_of_week_long_thursday">"Jueves"</string>
+    <string name="day_of_week_long_friday">"Viernes"</string>
+    <string name="day_of_week_long_saturday">"Sábado"</string>
     <string name="day_of_week_medium_sunday">"Dom"</string>
     <string name="day_of_week_medium_monday">"Lun"</string>
     <string name="day_of_week_medium_tuesday">"Mar"</string>
-    <string name="day_of_week_medium_wednesday">"mié"</string>
+    <string name="day_of_week_medium_wednesday">"Mié"</string>
     <string name="day_of_week_medium_thursday">"Jue"</string>
-    <string name="day_of_week_medium_friday">"vie"</string>
+    <string name="day_of_week_medium_friday">"Vie"</string>
     <string name="day_of_week_medium_saturday">"Sáb"</string>
     <string name="day_of_week_short_sunday">"Do"</string>
     <string name="day_of_week_short_monday">"Lu"</string>
@@ -646,38 +646,38 @@
     <string name="day_of_week_shortest_wednesday">"Mi"</string>
     <string name="day_of_week_shortest_thursday">"M"</string>
     <string name="day_of_week_shortest_friday">"V"</string>
-    <string name="day_of_week_shortest_saturday">"S"</string>
-    <string name="month_long_january">"enero"</string>
-    <string name="month_long_february">"febrero"</string>
-    <string name="month_long_march">"marzo"</string>
-    <string name="month_long_april">"abril"</string>
-    <string name="month_long_may">"mayo"</string>
-    <string name="month_long_june">"junio"</string>
-    <string name="month_long_july">"julio"</string>
-    <string name="month_long_august">"agosto"</string>
-    <string name="month_long_september">"septiembre"</string>
-    <string name="month_long_october">"octubre"</string>
-    <string name="month_long_november">"noviembre"</string>
-    <string name="month_long_december">"diciembre"</string>
-    <string name="month_medium_january">"ene"</string>
-    <string name="month_medium_february">"feb"</string>
-    <string name="month_medium_march">"mar"</string>
-    <string name="month_medium_april">"abr"</string>
-    <string name="month_medium_may">"may"</string>
-    <string name="month_medium_june">"jun"</string>
-    <string name="month_medium_july">"jul"</string>
-    <string name="month_medium_august">"ago."</string>
-    <string name="month_medium_september">"sep"</string>
+    <string name="day_of_week_shortest_saturday">"D"</string>
+    <string name="month_long_january">"Enero"</string>
+    <string name="month_long_february">"Febrero"</string>
+    <string name="month_long_march">"Marzo"</string>
+    <string name="month_long_april">"Abril"</string>
+    <string name="month_long_may">"Mayo"</string>
+    <string name="month_long_june">"Junio"</string>
+    <string name="month_long_july">"Julio"</string>
+    <string name="month_long_august">"Agosto"</string>
+    <string name="month_long_september">"Septiembre"</string>
+    <string name="month_long_october">"Octubre"</string>
+    <string name="month_long_november">"Noviembre"</string>
+    <string name="month_long_december">"Diciembre"</string>
+    <string name="month_medium_january">"Ene"</string>
+    <string name="month_medium_february">"Feb"</string>
+    <string name="month_medium_march">"Mar"</string>
+    <string name="month_medium_april">"Abr"</string>
+    <string name="month_medium_may">"May"</string>
+    <string name="month_medium_june">"Jun"</string>
+    <string name="month_medium_july">"Jul"</string>
+    <string name="month_medium_august">"Ago"</string>
+    <string name="month_medium_september">"Sep"</string>
     <string name="month_medium_october">"Oct"</string>
-    <string name="month_medium_november">"nov"</string>
-    <string name="month_medium_december">"dic"</string>
+    <string name="month_medium_november">"Nov"</string>
+    <string name="month_medium_december">"Dic"</string>
     <string name="month_shortest_january">"E"</string>
-    <string name="month_shortest_february">"F"</string>
+    <string name="month_shortest_february">"V"</string>
     <string name="month_shortest_march">"Mz"</string>
     <string name="month_shortest_april">"A"</string>
     <string name="month_shortest_may">"My"</string>
-    <string name="month_shortest_june">"Jn"</string>
-    <string name="month_shortest_july">"Jl"</string>
+    <string name="month_shortest_june">"J"</string>
+    <string name="month_shortest_july">"E"</string>
     <string name="month_shortest_august">"Ag"</string>
     <string name="month_shortest_september">"S"</string>
     <string name="month_shortest_october">"O"</string>
@@ -762,8 +762,8 @@
     <string name="usb_storage_button_unmount">"No activar"</string>
     <string name="usb_storage_error_message">"Se ha producido un problema al intentar utilizar la tarjeta SD para el almacenamiento USB."</string>
     <string name="usb_storage_notification_title">"Conectado por USB"</string>
-    <string name="usb_storage_notification_message">"Para copiar archivos al/desde el equipo"</string>
-    <string name="usb_storage_stop_notification_title">"Desactivar almacenamiento USB"</string>
+    <string name="usb_storage_notification_message">"Seleccionar para copiar archivos al/desde el equipo"</string>
+    <string name="usb_storage_stop_notification_title">"Desactivar almacenar en USB"</string>
     <string name="usb_storage_stop_notification_message">"Seleccionar para desactivar USB."</string>
     <string name="usb_storage_stop_title">"Desactivar almacenamiento USB"</string>
     <string name="usb_storage_stop_message">"Antes de desactivar el almacenamiento USB, asegúrate de haber desactivado el host USB. Selecciona \"Desactivar\" para desactivar el almacenamiento USB."</string>
@@ -792,7 +792,7 @@
     <string name="activity_list_empty">"No se ha encontrado ninguna actividad coincidente."</string>
     <string name="permlab_pkgUsageStats">"actualizar estadísticas de uso de componentes"</string>
     <string name="permdesc_pkgUsageStats">"Permite la modificación de estadísticas recopiladas sobre el uso de componentes. No está destinado al uso por parte de aplicaciones normales."</string>
-    <string name="tutorial_double_tap_to_zoom_message_short">"Da dos toques para acceder al control de zoom."</string>
+    <string name="tutorial_double_tap_to_zoom_message_short">"Pulsa dos veces para acceder al control de zoom."</string>
     <string name="gadget_host_error_inflating">"Error al aumentar el widget"</string>
     <string name="ime_action_go">"Ir"</string>
     <string name="ime_action_search">"Buscar"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 472c81d5b..c664d1a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -27,33 +27,33 @@
     <string name="unknownName">"(Inconnu)"</string>
     <string name="defaultVoiceMailAlphaTag">"Messagerie vocale"</string>
     <string name="defaultMsisdnAlphaTag">"MSISDN1"</string>
-    <string name="mmiError">"Problème de connexion ou code IHM non valide."</string>
+    <string name="mmiError">"Problème de connexion ou code MMI non valide."</string>
     <string name="serviceEnabled">"Le service a été activé."</string>
     <string name="serviceEnabledFor">"Ce service a été activé pour :"</string>
     <string name="serviceDisabled">"Ce service a été désactivé."</string>
     <string name="serviceRegistered">"Enregistrement réussi."</string>
     <string name="serviceErased">"Effacement réussi."</string>
     <string name="passwordIncorrect">"Le mot de passe est incorrect."</string>
-    <string name="mmiComplete">"IHM terminée."</string>
+    <string name="mmiComplete">"MMI terminé."</string>
     <string name="badPin">"L\'ancien code PIN saisi est incorrect."</string>
-    <string name="badPuk">"La clé PUK saisie est incorrecte."</string>
+    <string name="badPuk">"Le code PUK saisi est incorrect."</string>
     <string name="mismatchPin">"Les codes PIN saisis ne correspondent pas."</string>
     <string name="invalidPin">"Le code PIN doit compter de 4 à 8 chiffres."</string>
-    <string name="needPuk">"Votre carte SIM est verrouillée par clé PUK. Saisissez la clé PUK pour la déverrouiller."</string>
-    <string name="needPuk2">"Saisissez la clé PUK2 pour débloquer la carte SIM."</string>
-    <string name="ClipMmi">"Numéro de l\'appelant (entrant)"</string>
-    <string name="ClirMmi">"Numéro de l\'appelant (sortant)"</string>
+    <string name="needPuk">"Votre carte SIM est verrouillée par code PUK. Saisissez le code PUK pour la déverrouiller."</string>
+    <string name="needPuk2">"Saisissez le code PUK2 pour débloquer la carte SIM."</string>
+    <string name="ClipMmi">"Identifiant d\'appelant entrant"</string>
+    <string name="ClirMmi">"Identifiant d\'appelant sortant"</string>
     <string name="CfMmi">"Transfert d\'appel"</string>
     <string name="CwMmi">"Appel en attente"</string>
     <string name="BaMmi">"Interdiction d\'appel"</string>
     <string name="PwdMmi">"Modification du mot de passe"</string>
     <string name="PinMmi">"Modification du code PIN"</string>
-    <string name="CLIRDefaultOnNextCallOn">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : restreint"</string>
-    <string name="CLIRDefaultOnNextCallOff">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint"</string>
-    <string name="CLIRDefaultOffNextCallOn">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : restreint"</string>
-    <string name="CLIRDefaultOffNextCallOff">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint"</string>
+    <string name="CLIRDefaultOnNextCallOn">"Par défaut, les identifiants d\'appelant sont restreints. Appel suivant : restreint"</string>
+    <string name="CLIRDefaultOnNextCallOff">"Par défaut, les identifiants d\'appelant sont restreints. Appel suivant : non restreint"</string>
+    <string name="CLIRDefaultOffNextCallOn">"Par défaut, les identifiants d\'appelant ne sont pas restreints. Appel suivant : restreint"</string>
+    <string name="CLIRDefaultOffNextCallOff">"Par défaut, les identifiants d\'appelant ne sont pas restreints. Appel suivant : non restreint"</string>
     <string name="serviceNotProvisioned">"Ce service n\'est pas pris en charge."</string>
-    <string name="CLIRPermanent">"Le paramètre Numéro de l\'appelant ne peut pas être modifié."</string>
+    <string name="CLIRPermanent">"Le paramètre Identifiant d\'appelant ne peut pas être modifié."</string>
     <string name="RestrictedChangedTitle">"L\'accès limité a été modifié."</string>
     <string name="RestrictedOnData">"Le service de données est bloqué."</string>
     <string name="RestrictedOnEmergency">"Le service d\'appel d\'urgence est bloqué."</string>
@@ -247,12 +247,12 @@
     <string name="permdesc_readCalendar">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
     <string name="permlab_writeCalendar">"Écriture des données de l\'agenda"</string>
     <string name="permdesc_writeCalendar">"Permet à une application de modifier les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de votre agenda."</string>
-    <string name="permlab_accessMockLocation">"Création de sources de positionnement fictives à des fins de test"</string>
-    <string name="permdesc_accessMockLocation">"Permet de créer des sources de positionnement fictives à des fins de test. Des applications malveillantes peuvent utiliser cette fonctionnalité pour remplacer la position géographique et/ou l\'état fournis par des sources réelles comme le GPS ou les fournisseurs d\'accès."</string>
+    <string name="permlab_accessMockLocation">"Création de sources géographiques fictives à des fins de test"</string>
+    <string name="permdesc_accessMockLocation">"Permet de créer des sources de position géographique fictives à des fins de test. Des applications malveillantes peuvent utiliser cette fonctionnalité pour remplacer la position géographique et/ou l\'état fournis par des sources réelles comme le GPS ou les fournisseurs d\'accès."</string>
     <string name="permlab_accessLocationExtraCommands">"Accès aux commandes de fournisseur de position géographique supplémentaires"</string>
     <string name="permdesc_accessLocationExtraCommands">"Permet d\'accéder à des commandes de fournisseur de position géographique supplémentaires. Des applications malveillantes peuvent utiliser cette fonctionnalité pour interférer avec l\'utilisation du GPS ou d\'autres sources de positionnement géographique."</string>
     <string name="permlab_accessFineLocation">"Localisation OK (GPS)"</string>
-    <string name="permdesc_accessFineLocation">"Permet d\'accéder à des sources de positionnement précises comme le Global Positioning System (GPS) sur le téléphone, lorsque ces services sont disponibles. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer l\'endroit où vous vous trouvez et augmenter la consommation de la batterie de votre téléphone."</string>
+    <string name="permdesc_accessFineLocation">"Permet d\'accéder à des sources de positionnement géographique précises comme le Global Positioning System (GPS) sur le téléphone, lorsque ces services sont disponibles. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer l\'endroit où vous vous trouvez et augmenter la consommation de la batterie de votre téléphone."</string>
     <string name="permlab_accessCoarseLocation">"Position géo. approximative (selon le réseau)"</string>
     <string name="permdesc_accessCoarseLocation">"Accès à des sources de positionnement approximatif (par ex. des bases de données de réseaux mobiles) pour déterminer la position géographique du téléphone, lorsque cette option est disponible. Des applications malveillantes peuvent utiliser cette fonctionnalité pour déterminer approximativement l\'endroit où vous vous trouvez."</string>
     <string name="permlab_accessSurfaceFlinger">"Accès à SurfaceFlinger"</string>
@@ -284,13 +284,13 @@
     <string name="permlab_callPrivileged">"Appel direct de tout numéro de téléphone"</string>
     <string name="permdesc_callPrivileged">"Permet à une application d\'appeler tout numéro de téléphone (y compris les numéros d\'urgence) sans votre intervention. Des applications malveillantes peuvent passer des appels non nécessaires ou illégitimes à des services d\'urgence."</string>
     <string name="permlab_locationUpdates">"Contrôle des notifications de mise à jour de position géo."</string>
-    <string name="permdesc_locationUpdates">"Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant du signal radio. Les applications normales n\'utilisent pas cette fonctionnalité."</string>
+    <string name="permdesc_locationUpdates">"Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant de la radio. Les applications normales n\'utilisent pas cette fonctionnalité."</string>
     <string name="permlab_checkinProperties">"Accès aux propriétés d\'enregistrement"</string>
     <string name="permdesc_checkinProperties">"Permet un accès en lecture/écriture à des propriétés envoyées par le service d\'inscription. Les applications normales n\'utilisent pas cette fonctionnalité."</string>
     <string name="permlab_bindGadget">"choisir les widgets"</string>
     <string name="permdesc_bindGadget">"Permet à l\'application de signaler au système quels widgets peuvent être utilisés par quelle application. Grâce à cette autorisation, les applications peuvent accorder l\'accès à des données personnelles à d\'autres applications. Cette option n\'est pas utilisée par les applications standard."</string>
     <string name="permlab_modifyPhoneState">"Modification de l\'état du téléphone"</string>
-    <string name="permdesc_modifyPhoneState">"Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer le signal radio du téléphone, etc., sans vous en avertir."</string>
+    <string name="permdesc_modifyPhoneState">"Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer la radio du téléphone, etc., sans vous en avertir."</string>
     <string name="permlab_readPhoneState">"Lecture de l\'état du téléphone"</string>
     <string name="permdesc_readPhoneState">"Permet à l\'application d\'accéder aux fonctionnalités d\'appel du téléphone. L\'application peut alors déterminer le numéro de téléphone de l\'appareil, savoir si un appel est en cours, identifier le numéro appelé, etc."</string>
     <string name="permlab_wakeLock">"Arrêt du mode veille sur le téléphone"</string>
@@ -300,9 +300,9 @@
     <string name="permlab_factoryTest">"Exécution en mode Test d\'usine"</string>
     <string name="permdesc_factoryTest">"Permet d\'exécuter en tant que test fabricant de faible niveau en autorisant l\'accès au matériel du téléphone. Cette fonctionnalité est uniquement disponible lorsque le téléphone est en mode de test fabricant."</string>
     <string name="permlab_setWallpaper">"Configuration du fond d\'écran"</string>
-    <string name="permdesc_setWallpaper">"Permet à une application de définir le fond d\'écran du système."</string>
+    <string name="permdesc_setWallpaper">"Permet à une application de définir l\'arrière-plan du système."</string>
     <string name="permlab_setWallpaperHints">"Sélection de la la taille du fond d\'écran"</string>
-    <string name="permdesc_setWallpaperHints">"Permet à une application de définir la taille du fond d\'écran."</string>
+    <string name="permdesc_setWallpaperHints">"Permet à une application de définir la taille d\'arrière-plan du système."</string>
     <string name="permlab_masterClear">"Réinitialisation du système à ses paramètres d\'usine"</string>
     <string name="permdesc_masterClear">"Permet à une application de réinitialiser entièrement le système afin de rétablir ses valeurs d\'usine et d\'effacer toutes les données, configurations et applications installées."</string>
     <string name="permlab_setTimeZone">"Sélection du fuseau horaire"</string>
@@ -345,7 +345,7 @@
     <string name="permdesc_writeDictionary">"Permet à une application d\'enregistrer de nouveaux mots dans le dictionnaire personnel de l\'utilisateur."</string>
   <string-array name="phoneTypes">
     <item>"Domicile"</item>
-    <item>"Portable"</item>
+    <item>"Mobile"</item>
     <item>"Bureau"</item>
     <item>"Télécopie bureau"</item>
     <item>"Télécopie domicile"</item>
@@ -394,7 +394,7 @@
     <string name="lockscreen_screen_locked">"Écran verrouillé"</string>
     <string name="lockscreen_instructions_when_pattern_enabled">"Appuyez sur \"Menu\" pour débloquer le téléphone ou appeler un numéro d\'urgence"</string>
     <string name="lockscreen_instructions_when_pattern_disabled">"Appuyez sur \"Menu\" pour déverrouiller le téléphone."</string>
-    <string name="lockscreen_pattern_instructions">"Dessinez un schéma pour déverrouiller le téléphone"</string>
+    <string name="lockscreen_pattern_instructions">"Dessinez un motif pour déverrouiller le téléphone"</string>
     <string name="lockscreen_emergency_call">"Appel d\'urgence"</string>
     <string name="lockscreen_pattern_correct">"Combinaison correcte !"</string>
     <string name="lockscreen_pattern_wrong">"Désolé. Merci de réessayer."</string>
@@ -404,15 +404,15 @@
     <string name="lockscreen_missing_sim_message">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
     <string name="lockscreen_missing_sim_instructions">"Insérez une carte SIM."</string>
     <string name="lockscreen_network_locked_message">"Réseau verrouillé"</string>
-    <string name="lockscreen_sim_puk_locked_message">"La carte SIM est verrouillée par clé PUK."</string>
+    <string name="lockscreen_sim_puk_locked_message">"La carte SIM est verrouillée par code PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions">"Veuillez consulter le guide d\'utilisation ou contacter l\'assistance clientèle."</string>
-    <string name="lockscreen_sim_locked_message">"La carte SIM est verrouillée."</string>
+    <string name="lockscreen_sim_locked_message">"Téléphone verrouillé"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Déblocage de la carte SIM..."</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message">"Vous avez mal reproduit le schéma de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin">"Vous avez mal saisi le schéma de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. Au bout de <xliff:g id="NUMBER_1">%d</xliff:g> tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message">"Vous avez mal reproduit le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin">"Vous avez mal saisi le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. Au bout de <xliff:g id="NUMBER_1">%d</xliff:g> tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown">"Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
-    <string name="lockscreen_forgot_pattern_button_text">"Schéma oublié ?"</string>
-    <string name="lockscreen_glogin_too_many_attempts">"Trop de tentatives !"</string>
+    <string name="lockscreen_forgot_pattern_button_text">"Motif oublié ?"</string>
+    <string name="lockscreen_glogin_too_many_attempts">"Trop de tentatives de motif !"</string>
     <string name="lockscreen_glogin_instructions">"Pour déverrouiller le téléphone, connectez-vous à l\'aide de votre compte Google."</string>
     <string name="lockscreen_glogin_username_hint">"Nom d\'utilisateur (e-mail)"</string>
     <string name="lockscreen_glogin_password_hint">"Mot de passe"</string>
@@ -528,8 +528,8 @@
     <string name="days">"jours"</string>
     <string name="hour">"heure"</string>
     <string name="hours">"heures"</string>
-    <string name="minute">"mn"</string>
-    <string name="minutes">"mn"</string>
+    <string name="minute">"min"</string>
+    <string name="minutes">"min"</string>
     <string name="second">"s"</string>
     <string name="seconds">"s"</string>
     <string name="week">"semaine"</string>
@@ -609,7 +609,7 @@
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
-    <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string>
+    <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"dimanche"</string>
@@ -619,7 +619,7 @@
     <string name="day_of_week_long_thursday">"jeudi"</string>
     <string name="day_of_week_long_friday">"vendredi"</string>
     <string name="day_of_week_long_saturday">"samedi"</string>
-    <string name="day_of_week_medium_sunday">"Dim"</string>
+    <string name="day_of_week_medium_sunday">"dim."</string>
     <string name="day_of_week_medium_monday">"Lun"</string>
     <string name="day_of_week_medium_tuesday">"Mar"</string>
     <string name="day_of_week_medium_wednesday">"Mer"</string>
@@ -757,7 +757,7 @@
     <string name="perms_show_all"><b>"Tout afficher"</b></string>
     <string name="googlewebcontenthelper_loading">"Chargement..."</string>
     <string name="usb_storage_title">"Connecté à l\'aide d\'un câble USB"</string>
-    <string name="usb_storage_message">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez Monter pour copier des fichiers de votre ordinateur vers votre carte SD, ou inversement."</string>
+    <string name="usb_storage_message">"Vous avez connecté votre téléphone à votre ordinateur à l\'aide d\'un câble USB. Sélectionnez Monter pour copier des fichiers depuis votre ordinateur vers votre carte SD ou inversement."</string>
     <string name="usb_storage_button_mount">"Monter"</string>
     <string name="usb_storage_button_unmount">"Ne pas monter"</string>
     <string name="usb_storage_error_message">"Un problème est survenu lors de l\'utilisation de votre carte SD en tant que périphérique de stockage USB."</string>
@@ -798,7 +798,7 @@
     <string name="ime_action_search">"Rechercher"</string>
     <string name="ime_action_send">"Envoyer"</string>
     <string name="ime_action_next">"Suivant"</string>
-    <string name="ime_action_done">"OK"</string>
+    <string name="ime_action_done">"Terminé"</string>
     <string name="ime_action_default">"Exécuter"</string>
     <string name="dial_number_using">"Composer le numéro"\n"en utilisant <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using">"Ajouter un contact"\n"en utilisant <xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 4681e20..f80a4f4 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -108,9 +108,9 @@
     <string name="global_action_toggle_silent_mode">"Modalità silenziosa"</string>
     <string name="global_action_silent_mode_on_status">"Audio non attivo"</string>
     <string name="global_action_silent_mode_off_status">"Audio attivo"</string>
-    <string name="global_actions_toggle_airplane_mode">"Modalità aereo attiva"</string>
-    <string name="global_actions_airplane_mode_on_status">"Modalità aereo attiva"</string>
-    <string name="global_actions_airplane_mode_off_status">"Modalità aereo non attiva"</string>
+    <string name="global_actions_toggle_airplane_mode">"Modalità in volo"</string>
+    <string name="global_actions_airplane_mode_on_status">"Modalità in volo attiva"</string>
+    <string name="global_actions_airplane_mode_off_status">"Modalità in volo non attiva"</string>
     <string name="safeMode">"Modalità provvisoria"</string>
     <string name="android_system_label">"Sistema Android"</string>
     <string name="permgrouplab_costMoney">"Servizi che prevedono un costo"</string>
@@ -566,9 +566,9 @@
     <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
-    <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
     <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
@@ -579,7 +579,7 @@
     <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
     <!-- no translation found for month (7026169712234774086) -->
     <skip />
-    <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
     <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
@@ -722,7 +722,7 @@
     <string name="force_close">"Termina"</string>
     <string name="wait">"Attendi"</string>
     <string name="debug">"Debug"</string>
-    <string name="sendText">"Selezione un\'opzione di invio"</string>
+    <string name="sendText">"Seleziona un\'azione per il testo"</string>
     <string name="volume_ringtone">"Volume suoneria"</string>
     <string name="volume_music">"Volume app. multimediali"</string>
     <string name="volume_music_hint_playing_through_bluetooth">"Riproduzione tramite Bluetooth"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3ed17b5..8da040e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -249,7 +249,7 @@
     <string name="permdesc_writeCalendar">"端末に保存したカレンダーの予定の変更をアプリケーションに許可します。悪意のあるアプリケーションが、カレンダーデータを消去/変更する恐れがあります。"</string>
     <string name="permlab_accessMockLocation">"仮の位置情報でテスト"</string>
     <string name="permdesc_accessMockLocation">"テスト用に仮の位置情報源を作成します。これにより悪意のあるアプリケーションが、GPS、ネットワークプロバイダなどから返される本当の位置情報や状況を改ざんする恐れがあります。"</string>
-    <string name="permlab_accessLocationExtraCommands">"位置情報提供者の追加コマンドアクセス"</string>
+    <string name="permlab_accessLocationExtraCommands">"位置情報プロバイダのその他のコマンドへのアクセス"</string>
     <string name="permdesc_accessLocationExtraCommands">"位置情報提供元の追加コマンドにアクセスします。悪意のあるアプリケーションがGPSなどの位置提供の動作を妨害する恐れがあります。"</string>
     <string name="permlab_accessFineLocation">"精細な位置情報(GPS)"</string>
     <string name="permdesc_accessFineLocation">"GPSなど携帯電話の位置情報にアクセスします(可能な場合)。今いる場所が悪意のあるアプリケーションに検出されたり、バッテリーの消費が増える恐れがあります。"</string>
@@ -392,7 +392,7 @@
     <string name="emergency_call_dialog_number_for_display">"緊急通報番号"</string>
     <string name="lockscreen_carrier_default">"(通信サービスなし)"</string>
     <string name="lockscreen_screen_locked">"画面ロック中"</string>
-    <string name="lockscreen_instructions_when_pattern_enabled">"MENUキーでロック解除(または緊急通報)"</string>
+    <string name="lockscreen_instructions_when_pattern_enabled">"MENUキーでロック解除(または緊急通報)"</string>
     <string name="lockscreen_instructions_when_pattern_disabled">"MENUキーでロック解除"</string>
     <string name="lockscreen_pattern_instructions">"ロックを解除するパターンを入力"</string>
     <string name="lockscreen_emergency_call">"緊急通報"</string>
@@ -425,7 +425,7 @@
     <string name="hour_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="status_bar_clear_all_button">"通知を消去"</string>
     <string name="status_bar_no_notifications_title">"通知なし"</string>
-    <string name="status_bar_ongoing_events_title">"実行中"</string>
+    <string name="status_bar_ongoing_events_title">"操作中"</string>
     <string name="status_bar_latest_events_title">"通知"</string>
     <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="battery_status_charging">"充電中..."</string>
@@ -570,7 +570,7 @@
     <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'年'<xliff:g id="MONTH">MMMM</xliff:g>'月'<xliff:g id="DAY">d</xliff:g>'日'"</string>
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>'年'"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'/'<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="twelve_hour_time_format" format="date">"<xliff:g id="AMPM">a</xliff:g><xliff:g id="HOUR">h</xliff:g>'時'<xliff:g id="MINUTE">mm</xliff:g>'分'"</string>
+    <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
     <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"正午"</string>
     <string name="Noon">"正午"</string>
@@ -731,7 +731,7 @@
     <string name="volume_alarm">"アラームの音量"</string>
     <string name="volume_notification">"通知音量"</string>
     <string name="volume_unknown">"音量"</string>
-    <string name="ringtone_default">"プリセット着信音"</string>
+    <string name="ringtone_default">"デフォルトの着信音"</string>
     <string name="ringtone_default_with_actual">"端末の基本着信音(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent">"サイレント"</string>
     <string name="ringtone_picker_title">"着信音"</string>
@@ -788,7 +788,7 @@
     <string name="ext_media_safe_unmount_notification_title">"SDカードを安全に取り外しました"</string>
     <string name="ext_media_safe_unmount_notification_message">"SDカードを安全に取り外せます。"</string>
     <string name="ext_media_nomedia_notification_title">"SDカードが取り外されています"</string>
-    <string name="ext_media_nomedia_notification_message">"SDカードがありません。メモリを使用する際はカードを挿入してください。"</string>
+    <string name="ext_media_nomedia_notification_message">"SDカードが取り外されました。新しいSDカードを挿入して端末のメモリを増やしてください。"</string>
     <string name="activity_list_empty">"一致するアクティビティが見つかりません"</string>
     <string name="permlab_pkgUsageStats">"コンポーネント使用状況に関する統計情報の更新"</string>
     <string name="permdesc_pkgUsageStats">"収集されたコンポーネント使用状況に関する統計情報の変更を許可します。通常のアプリケーションでは使用しません。"</string>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/core/res/res/values-mcc204-es-rUS/strings.xml
similarity index 66%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to core/res/res/values-mcc204-es-rUS/strings.xml
index 674787e..7d96230 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/core/res/res/values-mcc204-es-rUS/strings.xml
@@ -1,22 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<?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.
 -->
-
-<resources>
-    <item type="configVarying" name="simple">simple finger</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
-    </bag>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="locale_replacement">"nl_nl"</string>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/core/res/res/values-mcc230-es-rUS/strings.xml
similarity index 66%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to core/res/res/values-mcc230-es-rUS/strings.xml
index 674787e..d3ecdbb 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/core/res/res/values-mcc230-es-rUS/strings.xml
@@ -1,22 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<?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.
 -->
-
-<resources>
-    <item type="configVarying" name="simple">simple finger</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
-    </bag>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="locale_replacement">"cs_cz"</string>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/core/res/res/values-mcc232-es-rUS/strings.xml
similarity index 66%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to core/res/res/values-mcc232-es-rUS/strings.xml
index 674787e..4773838 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/core/res/res/values-mcc232-es-rUS/strings.xml
@@ -1,22 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<?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.
 -->
-
-<resources>
-    <item type="configVarying" name="simple">simple finger</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
-    </bag>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="locale_replacement">"de_at"</string>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/core/res/res/values-mcc234-es-rUS/strings.xml
similarity index 66%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to core/res/res/values-mcc234-es-rUS/strings.xml
index 674787e..2538b73 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/core/res/res/values-mcc234-es-rUS/strings.xml
@@ -1,22 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<?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.
 -->
-
-<resources>
-    <item type="configVarying" name="simple">simple finger</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
-    </bag>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="locale_replacement">"en_gb"</string>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/core/res/res/values-mcc260-es-rUS/strings.xml
similarity index 66%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to core/res/res/values-mcc260-es-rUS/strings.xml
index 674787e..1161f9a 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/core/res/res/values-mcc260-es-rUS/strings.xml
@@ -1,22 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<?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.
 -->
-
-<resources>
-    <item type="configVarying" name="simple">simple finger</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
-    </bag>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="locale_replacement">"pl_pl"</string>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/core/res/res/values-mcc262-es-rUS/strings.xml
similarity index 66%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to core/res/res/values-mcc262-es-rUS/strings.xml
index 674787e..9505cf4 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/core/res/res/values-mcc262-es-rUS/strings.xml
@@ -1,22 +1,19 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<?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.
 -->
-
-<resources>
-    <item type="configVarying" name="simple">simple finger</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
-    </bag>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="locale_replacement">"de_de"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index a79d17e..7bed159 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -54,11 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Nummervisning er ikke begrenset som standard. Neste anrop: Ikke begrenset"</string>
     <string name="serviceNotProvisioned">"SIM-kortet er ikke tilrettelagt for tjenesten."</string>
     <string name="CLIRPermanent">"Kunne ikke endre innstilling for nummervisning."</string>
-    <string name="RestrictedChangedTitle">"Endring i begrenset tilgang"</string>
-    <string name="RestrictedOnData">"Datatjenesten er blokkert."</string>
-    <string name="RestrictedOnEmergency">"Nødtjenesten er blokkert."</string>
-    <string name="RestrictedOnNormal">"Tale- og SMS-tjenesten er blokkert."</string>
-    <string name="RestrictedOnAll">"Alle tale- og SMS-tjenester er blokkert."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Tale"</string>
     <string name="serviceClassData">"Data"</string>
     <string name="serviceClassFAX">"Fax"</string>
@@ -405,19 +410,20 @@
     <string name="lockscreen_missing_sim_instructions">"Sett inn et SIM-kort."</string>
     <string name="lockscreen_network_locked_message">"Nettverk ikke tillatt"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM-kortet er PUK-låst."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Se manualen eller kontakt kundeservice."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM-kortet er låst."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Låser opp SIM-kort…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Please try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string>
     <string name="lockscreen_failed_attempts_almost_glogin">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using your Google sign-in."\n\n" Please try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown">"Prøv igjen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Glemt mønsteret?"</string>
-    <string name="lockscreen_glogin_too_many_attempts">"For mange mønsterforsøk!"</string>
-    <string name="lockscreen_glogin_instructions">"For å låse opp, logg inn med Google-kontoen din"</string>
-    <string name="lockscreen_glogin_username_hint">"Brukernavn (e-post)"</string>
-    <string name="lockscreen_glogin_password_hint">"Passord"</string>
-    <string name="lockscreen_glogin_submit_button">"Logg inn"</string>
-    <string name="lockscreen_glogin_invalid_input">"Ugyldig brukernavn eller passord."</string>
+    <string name="lockscreen_glogin_too_many_attempts">"Too many pattern attempts!"</string>
+    <string name="lockscreen_glogin_instructions">"To unlock,BREAKsign in with your Google account"</string>
+    <string name="lockscreen_glogin_username_hint">"Username (email)"</string>
+    <string name="lockscreen_glogin_password_hint">"Password"</string>
+    <string name="lockscreen_glogin_submit_button">"Sign in"</string>
+    <string name="lockscreen_glogin_invalid_input">"Invalid username or password."</string>
     <string name="status_bar_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">AA</xliff:g>"</string>
     <string name="hour_minute_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
     <string name="hour_minute_cap_ampm">"<xliff:g id="HOUR">%-l</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
@@ -576,7 +582,8 @@
     <string name="Noon">"Middag"</string>
     <string name="midnight">"midnatt"</string>
     <string name="Midnight">"Midnatt"</string>
-    <string name="month_day">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
+    <!-- no translation found for month_day (3693060561170538204) -->
+    <skip />
     <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 2aed5b4..3a9e32c 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -619,34 +619,34 @@
     <string name="day_of_week_long_thursday">"Donderdag"</string>
     <string name="day_of_week_long_friday">"Vrijdag"</string>
     <string name="day_of_week_long_saturday">"Zaterdag"</string>
-    <string name="day_of_week_medium_sunday">"zo"</string>
-    <string name="day_of_week_medium_monday">"ma"</string>
-    <string name="day_of_week_medium_tuesday">"di"</string>
-    <string name="day_of_week_medium_wednesday">"wo"</string>
-    <string name="day_of_week_medium_thursday">"do"</string>
-    <string name="day_of_week_medium_friday">"vr"</string>
-    <string name="day_of_week_medium_saturday">"za"</string>
-    <string name="day_of_week_short_sunday">"zo"</string>
-    <string name="day_of_week_short_monday">"ma"</string>
-    <string name="day_of_week_short_tuesday">"di"</string>
-    <string name="day_of_week_short_wednesday">"wo"</string>
-    <string name="day_of_week_short_thursday">"do"</string>
-    <string name="day_of_week_short_friday">"vr"</string>
-    <string name="day_of_week_short_saturday">"za"</string>
-    <string name="day_of_week_shorter_sunday">"zo"</string>
-    <string name="day_of_week_shorter_monday">"m"</string>
-    <string name="day_of_week_shorter_tuesday">"di"</string>
-    <string name="day_of_week_shorter_wednesday">"w"</string>
-    <string name="day_of_week_shorter_thursday">"do"</string>
-    <string name="day_of_week_shorter_friday">"v"</string>
-    <string name="day_of_week_shorter_saturday">"za"</string>
-    <string name="day_of_week_shortest_sunday">"z"</string>
-    <string name="day_of_week_shortest_monday">"m"</string>
-    <string name="day_of_week_shortest_tuesday">"d"</string>
-    <string name="day_of_week_shortest_wednesday">"w"</string>
-    <string name="day_of_week_shortest_thursday">"d"</string>
-    <string name="day_of_week_shortest_friday">"v"</string>
-    <string name="day_of_week_shortest_saturday">"z"</string>
+    <string name="day_of_week_medium_sunday">"Zo"</string>
+    <string name="day_of_week_medium_monday">"Ma"</string>
+    <string name="day_of_week_medium_tuesday">"Di"</string>
+    <string name="day_of_week_medium_wednesday">"Wo"</string>
+    <string name="day_of_week_medium_thursday">"Do"</string>
+    <string name="day_of_week_medium_friday">"Vr"</string>
+    <string name="day_of_week_medium_saturday">"Za"</string>
+    <string name="day_of_week_short_sunday">"Zo"</string>
+    <string name="day_of_week_short_monday">"Ma"</string>
+    <string name="day_of_week_short_tuesday">"Di"</string>
+    <string name="day_of_week_short_wednesday">"Wo"</string>
+    <string name="day_of_week_short_thursday">"Do"</string>
+    <string name="day_of_week_short_friday">"Vr"</string>
+    <string name="day_of_week_short_saturday">"Za"</string>
+    <string name="day_of_week_shorter_sunday">"Zo"</string>
+    <string name="day_of_week_shorter_monday">"M"</string>
+    <string name="day_of_week_shorter_tuesday">"Di"</string>
+    <string name="day_of_week_shorter_wednesday">"W"</string>
+    <string name="day_of_week_shorter_thursday">"Do"</string>
+    <string name="day_of_week_shorter_friday">"V"</string>
+    <string name="day_of_week_shorter_saturday">"Za"</string>
+    <string name="day_of_week_shortest_sunday">"Z"</string>
+    <string name="day_of_week_shortest_monday">"M"</string>
+    <string name="day_of_week_shortest_tuesday">"D"</string>
+    <string name="day_of_week_shortest_wednesday">"W"</string>
+    <string name="day_of_week_shortest_thursday">"D"</string>
+    <string name="day_of_week_shortest_friday">"V"</string>
+    <string name="day_of_week_shortest_saturday">"Z"</string>
     <string name="month_long_january">"Januari"</string>
     <string name="month_long_february">"Februari"</string>
     <string name="month_long_march">"Maart"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 560bd5a..50d245b 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -41,19 +41,19 @@
     <string name="invalidPin">"Wpisz kod PIN o długości od 4 do 8 cyfr."</string>
     <string name="needPuk">"Karta SIM jest zablokowana kodem PUK. Wprowadź kod PUK, aby odblokować kartę."</string>
     <string name="needPuk2">"Wprowadź kod PUK2, aby odblokować kartę SIM."</string>
-    <string name="ClipMmi">"Identyfikator rozmówcy przy połączeniach przychodzących"</string>
-    <string name="ClirMmi">"Identyfikator rozmówcy przy połączeniach wychodzących"</string>
+    <string name="ClipMmi">"Identyfikator dzwoniącego przy połączeniach przychodzących"</string>
+    <string name="ClirMmi">"Identyfikator dzwoniącego przy połączeniach wychodzących"</string>
     <string name="CfMmi">"Przekierowania połączeń"</string>
     <string name="CwMmi">"Połączenia oczekujące"</string>
     <string name="BaMmi">"Blokada dzwonienia"</string>
     <string name="PwdMmi">"Zmiana hasła"</string>
     <string name="PinMmi">"Zmiana kodu PIN"</string>
-    <string name="CLIRDefaultOnNextCallOn">"Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony"</string>
-    <string name="CLIRDefaultOnNextCallOff">"Identyfikator rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
-    <string name="CLIRDefaultOffNextCallOn">"Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony"</string>
-    <string name="CLIRDefaultOffNextCallOff">"Identyfikator rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
+    <string name="CLIRDefaultOnNextCallOn">"Identyfikator dzwoniącego ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: zastrzeżony"</string>
+    <string name="CLIRDefaultOnNextCallOff">"Identyfikator dzwoniącego ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
+    <string name="CLIRDefaultOffNextCallOn">"Identyfikator dzwoniącego ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony"</string>
+    <string name="CLIRDefaultOffNextCallOff">"Identyfikator dzwoniącego ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
     <string name="serviceNotProvisioned">"Usługa nie jest świadczona."</string>
-    <string name="CLIRPermanent">"Nie można zmienić ustawienia identyfikatora rozmówcy."</string>
+    <string name="CLIRPermanent">"Nie można zmienić ustawienia identyfikatora dzwoniącego."</string>
     <string name="RestrictedChangedTitle">"Zmieniono ograniczenie dostępu"</string>
     <string name="RestrictedOnData">"Usługa transmisji danych jest zablokowana."</string>
     <string name="RestrictedOnEmergency">"Usługa połączeń alarmowych jest zablokowana."</string>
@@ -108,9 +108,9 @@
     <string name="global_action_toggle_silent_mode">"Tryb cichy"</string>
     <string name="global_action_silent_mode_on_status">"Dźwięk jest wyłączony"</string>
     <string name="global_action_silent_mode_off_status">"Dźwięk jest włączony"</string>
-    <string name="global_actions_toggle_airplane_mode">"Tryb samolotowy"</string>
-    <string name="global_actions_airplane_mode_on_status">"Tryb samolotowy jest włączony"</string>
-    <string name="global_actions_airplane_mode_off_status">"Tryb samolotowy jest wyłączony"</string>
+    <string name="global_actions_toggle_airplane_mode">"Tryb lotniczy"</string>
+    <string name="global_actions_airplane_mode_on_status">"Tryb lotniczy jest włączony"</string>
+    <string name="global_actions_airplane_mode_off_status">"Tryb lotniczy jest wyłączony"</string>
     <string name="safeMode">"Tryb awaryjny"</string>
     <string name="android_system_label">"System Android"</string>
     <string name="permgrouplab_costMoney">"Usługi płatne"</string>
@@ -311,7 +311,7 @@
     <string name="permdesc_getAccounts">"Pozwala aplikacji na pobranie listy kont zapisanych w telefonie."</string>
     <string name="permlab_accessNetworkState">"wyświetlanie stanu sieci"</string>
     <string name="permdesc_accessNetworkState">"Pozwala aplikacji na wyświetlanie stanu wszystkich sieci."</string>
-    <string name="permlab_createNetworkSockets">"pełen dostęp do internetu"</string>
+    <string name="permlab_createNetworkSockets">"pełen dostęp do Internetu"</string>
     <string name="permdesc_createNetworkSockets">"Pozwala aplikacji na tworzenie gniazd sieciowych."</string>
     <string name="permlab_writeApnSettings">"zapisywanie ustawień nazwy punktu dostępowego (APN, Access Point Name)"</string>
     <string name="permdesc_writeApnSettings">"Pozwala aplikacji na zmianę ustawień APN, takich jak serwer proxy oraz port dowolnego APN."</string>
@@ -566,10 +566,10 @@
     <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
-    <string name="full_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="full_date_month_first" format="date">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="full_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
     <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"południe"</string>
@@ -582,34 +582,34 @@
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="month_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
-    <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>, <xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
-    <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
-    <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
-    <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
-    <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
-    <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
-    <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
-    <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
-    <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>"</string>
-    <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
-    <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
-    <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+    <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
+    <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
+    <string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
+    <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string>
+    <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
+    <string name="numeric_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>"</string>
+    <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
+    <string name="same_month_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+    <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <string name="abbrev_month_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
-    <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string>
+    <string name="abbrev_month_day">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"niedziela"</string>
@@ -659,30 +659,30 @@
     <string name="month_long_october">"Październik"</string>
     <string name="month_long_november">"Listopad"</string>
     <string name="month_long_december">"Grudzień"</string>
-    <string name="month_medium_january">"sty"</string>
-    <string name="month_medium_february">"lut"</string>
-    <string name="month_medium_march">"mar"</string>
-    <string name="month_medium_april">"kwi"</string>
-    <string name="month_medium_may">"maj"</string>
-    <string name="month_medium_june">"cze"</string>
-    <string name="month_medium_july">"lip"</string>
-    <string name="month_medium_august">"sie"</string>
-    <string name="month_medium_september">"wrz"</string>
-    <string name="month_medium_october">"paź"</string>
-    <string name="month_medium_november">"lis"</string>
-    <string name="month_medium_december">"gru"</string>
-    <string name="month_shortest_january">"sty"</string>
-    <string name="month_shortest_february">"lut"</string>
-    <string name="month_shortest_march">"mar"</string>
-    <string name="month_shortest_april">"kwi"</string>
-    <string name="month_shortest_may">"maj"</string>
-    <string name="month_shortest_june">"cze"</string>
-    <string name="month_shortest_july">"lip"</string>
-    <string name="month_shortest_august">"sie"</string>
-    <string name="month_shortest_september">"wrz"</string>
-    <string name="month_shortest_october">"paź"</string>
-    <string name="month_shortest_november">"lis"</string>
-    <string name="month_shortest_december">"gru"</string>
+    <string name="month_medium_january">"Sty"</string>
+    <string name="month_medium_february">"Lut"</string>
+    <string name="month_medium_march">"Mar"</string>
+    <string name="month_medium_april">"Kwi"</string>
+    <string name="month_medium_may">"Maj"</string>
+    <string name="month_medium_june">"Cze"</string>
+    <string name="month_medium_july">"Lip"</string>
+    <string name="month_medium_august">"Sie"</string>
+    <string name="month_medium_september">"Wrz"</string>
+    <string name="month_medium_october">"Paź"</string>
+    <string name="month_medium_november">"Lis"</string>
+    <string name="month_medium_december">"Gru"</string>
+    <string name="month_shortest_january">"Sty"</string>
+    <string name="month_shortest_february">"Lut"</string>
+    <string name="month_shortest_march">"Pon"</string>
+    <string name="month_shortest_april">"Kwi"</string>
+    <string name="month_shortest_may">"Maj"</string>
+    <string name="month_shortest_june">"Cze"</string>
+    <string name="month_shortest_july">"Lip"</string>
+    <string name="month_shortest_august">"Sie"</string>
+    <string name="month_shortest_september">"Wrz"</string>
+    <string name="month_shortest_october">"Paź"</string>
+    <string name="month_shortest_november">"Lis"</string>
+    <string name="month_shortest_december">"Gru"</string>
     <string name="elapsed_time_short_format_mm_ss">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
     <string name="selectAll">"Zaznacz wszystko"</string>
@@ -731,8 +731,8 @@
     <string name="volume_alarm">"Głośność alarmu"</string>
     <string name="volume_notification">"Głośność powiadomienia"</string>
     <string name="volume_unknown">"Głośność"</string>
-    <string name="ringtone_default">"Dzwonek domyślny"</string>
-    <string name="ringtone_default_with_actual">"Dzwonek domyślny (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <string name="ringtone_default">"Domyślny dzwonek"</string>
+    <string name="ringtone_default_with_actual">"Domyślny dzwonek (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent">"Cichy"</string>
     <string name="ringtone_picker_title">"Dzwonki"</string>
     <string name="ringtone_unknown">"Nieznany dzwonek"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 81fd87d..7db73f0 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -115,6 +115,7 @@
         <item><xliff:g id="id">mute</xliff:g></item>
         <item><xliff:g id="id">speakerphone</xliff:g></item>
         <item><xliff:g id="id">wifi</xliff:g></item>
+        <item><xliff:g id="id">tty</xliff:g></item>
         <item><xliff:g id="id">bluetooth</xliff:g></item>
         <item><xliff:g id="id">gps</xliff:g></item>
         <item><xliff:g id="id">sync_active</xliff:g></item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 88b8316..972953b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -94,6 +94,11 @@
         <!-- Text color, typeface, size, and style for "small" inverse text. Defaults to secondary inverse text color. -->
         <attr name="textAppearanceSmallInverse" format="reference" />
 
+        <!-- Text color, typeface, size, and style for system search result title. Defaults to primary inverse text color. @hide -->	
+        <attr name="textAppearanceSearchResultTitle" format="reference" />	
+        <!-- Text color, typeface, size, and style for system search result subtitle. Defaults to primary inverse text color. @hide -->	
+        <attr name="textAppearanceSearchResultSubtitle" format="reference" />
+
         <!-- Text color, typeface, size, and style for the text inside of a button. -->
         <attr name="textAppearanceButton" format="reference" />
         
@@ -147,6 +152,8 @@
         <!-- The preferred list item height -->
         <attr name="listPreferredItemHeight" format="dimension" />
         <!-- The drawable for the list divider -->
+	<!-- The list item height for search results. @hide -->
+	<attr name="searchResultListItemHeight" format="dimension" />
         <attr name="listDivider" format="reference" />
         <!-- TextView style for list separators. -->
         <attr name="listSeparatorTextViewStyle" format="reference" />
@@ -2524,12 +2531,12 @@
     </declare-styleable>
 
     <declare-styleable name="AccelerateInterpolator">
-        <!-- This is the amount of deceleration to ad when easing in. -->
+        <!-- This is the amount of deceleration to add when easing in. -->
         <attr name="factor" format="float" />
     </declare-styleable>
     
     <declare-styleable name="DecelerateInterpolator">
-        <!-- This is the amount of acceleration to ad when easing out. -->
+        <!-- This is the amount of acceleration to add when easing out. -->
         <attr name="factor" />
     </declare-styleable>
     
@@ -2537,6 +2544,23 @@
         <attr name="cycles" format="float" />
     </declare-styleable>
 
+    <declare-styleable name="AnticipateInterpolator">
+        <!-- This is the amount of tension. -->
+        <attr name="tension" format="float" />
+    </declare-styleable>
+
+    <declare-styleable name="OvershootInterpolator">
+        <!-- This is the amount of tension. -->
+        <attr name="tension" />
+    </declare-styleable>
+
+    <declare-styleable name="AnticipateOvershootInterpolator">
+        <!-- This is the amount of tension. -->
+        <attr name="tension" />
+        <!-- This is the amount by which to multiply the tension. -->
+        <attr name="extraTension" format="float" />
+    </declare-styleable>
+
     <!-- ========================== -->
     <!-- State attributes           -->
     <!-- ========================== -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 093ddd3..54da326 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -769,6 +769,15 @@
         <attr name="name" />
     </declare-styleable>
     
+    <!-- The <code>supports-density</code> specifies a screen density that this
+         package supports. Application can specify multiple densities it supports.
+         <p>This appears as a child tag of the
+         {@link #AndroidManifestApplication application} tag. -->
+    <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifestApplication">
+        <!-- Required value of the density in dip (device independent pixel). -->
+        <attr name="density" format="integer" />
+    </declare-styleable>
+
     <!-- The <code>provider</code> tag declares a
          {@link android.content.ContentProvider} class that is available
          as part of the package's application components, supplying structured
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a7af68b..5b5e5c2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1085,4 +1085,22 @@
   <public type="integer" name="config_shortAnimTime" id="0x010e0000" />
   <public type="integer" name="config_mediumAnimTime" id="0x010e0001" />
   <public type="integer" name="config_longAnimTime" id="0x010e0002" />
+
+<!-- ===============================================================
+     Resources added in version 4 of the platform.
+     =============================================================== -->
+  <eat-comment />
+
+   <public type="attr" name="tension" id="0x0101026a" />
+   <public type="attr" name="extraTension" id="0x0101026b" />
+   <public type="attr" name="density" id="0x0101026c" />
+
+   <public type="anim" name="anticipate_interpolator" id="0x010a0007" />
+   <public type="anim" name="overshoot_interpolator" id="0x010a0008" />
+   <public type="anim" name="anticipate_overshoot_interpolator" id="0x010a0009" />
+   <public type="anim" name="bounce_interpolator" id="0x010a000a" />
+
+  <public type="drawable" name="stat_sys_vp_phone_call" id="0x0108022d" />
+  <public type="drawable" name="stat_sys_vp_phone_call_on_hold" id="0x0108022e" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e0bc9d2..c35676c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -97,6 +97,12 @@
     <string name="PwdMmi">Password change</string>
     <!-- Displayed as the title for a success/failure report changing the SIM PIN. -->
     <string name="PinMmi">PIN change</string>
+    <string name="CnipMmi">Calling number present</string>
+    <string name="CnirMmi">Calling number restricted</string>
+    <string name="ThreeWCMmi">Three way calling</string>
+    <string name="RuacMmi">Rejection of undesired annoying calls</string>
+    <string name="CndMmi">Calling number delivery</string>
+    <string name="DndMmi">Do not disturb</string>
 
     <!-- Displayed to confirm to the user that caller ID will be restricted on the next call as usual. -->
     <string name="CLIRDefaultOnNextCallOn">Caller ID defaults to restricted. Next call: Restricted</string>
@@ -162,6 +168,11 @@
     <string name="cfTemplateRegisteredTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: Not forwarded</string>
 
     <!-- android.net.http Error strings --> <skip />
+    <!-- Displayed when a feature code (non-phone number) is dialed and completes successfully. -->
+    <string name="fcComplete">Feature code complete.</string>
+    <!-- Displayed when a feature code (non-phone number) is dialed and completes unsuccessfully. -->
+    <string name="fcError">Connection problem or invalid feature code.</string>
+    <!-- android.net.http Error strings --> <skip />
     <!-- Displayed when a web request was successful. -->
     <string name="httpErrorOk">OK</string>
     <!-- Displayed when a web request failed because we don't know the exact reason. -->
@@ -324,6 +335,11 @@
     <string name="permgroupdesc_developmentTools">Features only needed for
         application developers.</string>
 
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_storage">Storage</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_storage">Access the SD card.</string>
+
     <!--  Permissions -->
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1034,6 +1050,11 @@
     <string name="permdesc_writeDictionary">Allows an application to write new words into the
       user dictionary.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_sdcardWrite">write to SD card</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_sdcardWrite">Allows an application to write to the SD card.</string>
+
     <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
     <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
     <string-array name="phoneTypes">
@@ -2290,6 +2311,7 @@
     <!-- Shown in the tutorial for tap twice for zoom control. -->
     <string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string>
 
+
     <!-- Shown in gadget hosts (e.g. the home screen) when there was an error inflating
     the gadget. -->
     <string name="gadget_host_error_inflating">Error inflating widget</string>
@@ -2316,6 +2338,7 @@
          ContactsProvider and GoogleContactsProvider -->
     <skip />
 
+
     <!-- This string appears (on two lines) when you type a number into contacts search, to let you dial the phone number you typed.  The first line will be in bigger type than the second. -->
     <string name="dial_number_using">Dial number\nusing <xliff:g id="number" example="555">%s</xliff:g></string>
 
@@ -2326,3 +2349,8 @@
     <string-array translatable="false" name="carrier_locales">
     </string-array>    
 </resources>
+
+
+
+
+
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index d7b654e..a436f61 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -138,6 +138,7 @@
     </style>
 
     <!-- Window animations that are applied to the search bar overlay window.
+	Previously used, but currently unused.
          {@hide Pending API council approval} -->
     <style name="Animation.SearchBar">
         <item name="windowEnterAnimation">@anim/search_bar_enter</item>
@@ -574,6 +575,24 @@
         <item name="android:textColor">@android:color/primary_text_light_disable_only</item>
     </style>
 
+    <!-- @hide -->	
+     <style name="TextAppearance.SearchResult">	
+         <item name="android:textStyle">normal</item>	
+         <item name="android:textColor">?textColorPrimaryInverse</item>	
+         <item name="android:textColorHint">?textColorHintInverse</item>	
+     </style>	
+     	
+     <!-- @hide -->	
+     <style name="TextAppearance.SearchResult.Title">	
+         <item name="android:textSize">16sp</item>	
+     </style>	
+     	
+     <!-- @hide -->	
+     <style name="TextAppearance.SearchResult.Subtitle">	
+         <item name="android:textSize">13sp</item>	
+         <item name="android:textColor">?textColorSecondaryInverse</item>	
+     </style>	
+
     <style name="TextAppearance.WindowTitle">
         <item name="android:textColor">#fff</item>
         <item name="android:textSize">14sp</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 6b3d740..dfd2391 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -57,6 +57,12 @@
         <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Large.Inverse</item>
         <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Medium.Inverse</item>
         <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item>
+
+        <!-- @hide -->
+        <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.SearchResult.Title</item>
+        
+        <!-- @hide -->
+        <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.SearchResult.Subtitle</item>
         
         <item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item>
         
@@ -75,6 +81,8 @@
 
         <!-- List attributes -->
         <item name="listPreferredItemHeight">64dip</item>
+        <!-- @hide -->
+        <item name="searchResultListItemHeight">58dip</item>
         <item name="listDivider">@drawable/divider_horizontal_dark</item>
         <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator</item>   
         
@@ -355,7 +363,6 @@
     <!-- Theme for the search input bar. -->
     <style name="Theme.SearchBar" parent="Theme.Panel">
         <item name="android:backgroundDimEnabled">true</item>
-        <item name="android:windowAnimationStyle">@android:style/Animation.SearchBar</item>
         <item name="windowContentOverlay">@null</item>        
     </style>
 
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index b13a292..f80bd6b 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -54,6 +54,10 @@
         <group gid="log" />
     </permission>
 
+    <permission name="android.permission.SDCARD_WRITE" >
+        <group gid="sdcard_rw" />
+    </permission>
+
     <!-- The group that /cache belongs to, linked to the permission
          set on the applications that can access /cache -->
     <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 3813d8f..9e88d7e 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -103,6 +103,36 @@
         public boolean inScaled;
 
         /**
+         * If this is set to true, then the resulting bitmap will allocate its
+         * pixels such that they can be purged if the system needs to reclaim
+         * memory. In that instance, when the pixels need to be accessed again
+         * (e.g. the bitmap is drawn, getPixels() is called), they will be
+         * automatically re-decoded.
+         *
+         * For the re-decode to happen, the bitmap must have access to the
+         * encoded data, either by sharing a reference to the input
+         * or by making a copy of it. This distinction is controlled by
+         * inInputShareable. If this is true, then the bitmap may keep a shallow
+         * reference to the input. If this is false, then the bitmap will
+         * explicitly make a copy of the input data, and keep that. Even if
+         * sharing is allowed, the implementation may still decide to make a
+         * deep copy of the input data.
+         *
+         * @hide pending API council approval
+         */
+        public boolean inPurgeable;
+
+        /**
+         * This field works in conjuction with inPurgeable. If inPurgeable is
+         * false, then this field is ignored. If inPurgeable is true, then this
+         * field determines whether the bitmap can share a reference to the
+         * input data (inputstream, array, etc.) or if it must make a deep copy.
+         *
+         * @hide pending API council approval
+         */
+        public boolean inInputShareable;
+
+        /**
          * The resulting width of the bitmap, set independent of the state of
          * inJustDecodeBounds. However, if there is an error trying to decode,
          * outWidth will be set to -1.
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 32ecd9f..06d53e3 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -112,7 +112,9 @@
      * on behalf of the Canvas. Any subsequent drawing with a GL-backed Canvas
      * will have to recreate those resources.
      */
-    public static native void freeGlCaches();
+    public static void freeGlCaches() {
+        freeCaches();
+    }
         
     /**
      * Specify a bitmap for the canvas to draw into.
@@ -1405,6 +1407,14 @@
         finalizer(mNativeCanvas);
     }
 
+    /**
+     * Free up as much memory as possible from private caches (e.g. fonts,
+     * images)
+     *
+     * @hide - for now
+     */
+    public static native void freeCaches();
+
     private static native int initRaster(int nativeBitmapOrZero);
     private static native int initGL();
     private static native void native_setBitmap(int nativeCanvas, int bitmap);
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index 2681eae..f549900 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import java.io.PrintWriter;
+
 
 /**
  * The Matrix class holds a 3x3 matrix for transforming coordinates.
@@ -539,17 +541,49 @@
     }
 
     public String toString() {
-        return "Matrix{" + toShortString() + "}";
+        StringBuilder sb = new StringBuilder(64);
+        sb.append("Matrix{");
+        toShortString(sb);
+        sb.append('}');
+        return sb.toString();
                 
     }
 
     public String toShortString() {
+        StringBuilder sb = new StringBuilder(64);
+        toShortString(sb);
+        return sb.toString();
+    }
+
+    /**
+     * @hide
+     */
+    public void toShortString(StringBuilder sb) {
         float[] values = new float[9];
         getValues(values);
-        return "[" +
-                values[0] + ", " + values[1] + ", " + values[2] + "][" +
-                values[3] + ", " + values[4] + ", " + values[5] + "][" +
-                values[6] + ", " + values[7] + ", " + values[8] + "]";
+        sb.append('[');
+        sb.append(values[0]); sb.append(", "); sb.append(values[1]); sb.append(", ");
+        sb.append(values[2]); sb.append("][");
+        sb.append(values[3]); sb.append(", "); sb.append(values[4]); sb.append(", ");
+        sb.append(values[5]); sb.append("][");
+        sb.append(values[6]); sb.append(", "); sb.append(values[7]); sb.append(", ");
+        sb.append(values[8]); sb.append(']');
+    }
+
+    /**
+     * Print short string, to optimize dumping.
+     * @hide
+     */
+    public void printShortString(PrintWriter pw) {
+        float[] values = new float[9];
+        getValues(values);
+        pw.print('[');
+        pw.print(values[0]); pw.print(", "); pw.print(values[1]); pw.print(", ");
+                pw.print(values[2]); pw.print("][");
+        pw.print(values[3]); pw.print(", "); pw.print(values[4]); pw.print(", ");
+                pw.print(values[5]); pw.print("][");
+        pw.print(values[6]); pw.print(", "); pw.print(values[7]); pw.print(", ");
+                pw.print(values[8]); pw.print(']');
                 
     }
 
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 2005344..50ab566 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.io.PrintWriter;
+
 /**
  * Rect holds four integer coordinates for a rectangle. The rectangle is
  * represented by the coordinates of its 4 edges (left, top, right bottom).
@@ -78,14 +80,40 @@
     }
 
     public String toString() {
-        return "Rect(" + left + ", " + top + " - " + right + ", " + bottom + ")";
+        StringBuilder sb = new StringBuilder(32);
+        sb.append("Rect("); sb.append(left); sb.append(", ");
+        sb.append(top); sb.append(" - "); sb.append(right);
+        sb.append(", "); sb.append(bottom); sb.append(")");
+        return sb.toString();
     }
 
     /**
      * Return a string representation of the rectangle in a compact form.
      */
     public String toShortString() {
-        return "[" + left + "," + top + "][" + right + "," + bottom + "]";
+        return toShortString(new StringBuilder(32));
+    }
+    
+    /**
+     * Return a string representation of the rectangle in a compact form.
+     * @hide
+     */
+    public String toShortString(StringBuilder sb) {
+        sb.setLength(0);
+        sb.append('['); sb.append(left); sb.append(',');
+        sb.append(top); sb.append("]["); sb.append(right);
+        sb.append(','); sb.append(bottom); sb.append(']');
+        return sb.toString();
+    }
+    
+    /**
+     * Print short representation to given writer.
+     * @hide
+     */
+    public void printShortString(PrintWriter pw) {
+        pw.print('['); pw.print(left); pw.print(',');
+        pw.print(top); pw.print("]["); pw.print(right);
+        pw.print(','); pw.print(bottom); pw.print(']');
     }
     
     /**
@@ -517,4 +545,17 @@
         right = in.readInt();
         bottom = in.readInt();
     }
+
+    /**
+     * Scales up the rect by the given scale.
+     * @hide
+     */
+    public void scale(float scale) {
+        if (scale != 1.0f) {
+            left *= scale;
+            top *= scale;
+            right *= scale;
+            bottom*= scale;
+        }
+    }
 }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 42e28e8..f0d49f5 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -38,32 +38,32 @@
  * dealing with an underlying visual resource that may take a variety of forms.
  * Unlike a {@link android.view.View}, a Drawable does not have any facility to
  * receive events or otherwise interact with the user.
- * 
+ *
  * <p>In addition to simple drawing, Drawable provides a number of generic
  * mechanisms for its client to interact with what is being drawn:
- * 
+ *
  * <ul>
  *     <li> The {@link #setBounds} method <var>must</var> be called to tell the
  *     Drawable where it is drawn and how large it should be.  All Drawables
  *     should respect the requested size, often simply by scaling their
  *     imagery.  A client can find the preferred size for some Drawables with
  *     the {@link #getIntrinsicHeight} and {@link #getIntrinsicWidth} methods.
- * 
+ *
  *     <li> The {@link #getPadding} method can return from some Drawables
  *     information about how to frame content that is placed inside of them.
  *     For example, a Drawable that is intended to be the frame for a button
  *     widget would need to return padding that correctly places the label
  *     inside of itself.
- * 
+ *
  *     <li> The {@link #setState} method allows the client to tell the Drawable
  *     in which state it is to be drawn, such as "focused", "selected", etc.
  *     Some drawables may modify their imagery based on the selected state.
- * 
+ *
  *     <li> The {@link #setLevel} method allows the client to supply a single
  *     continuous controller that can modify the Drawable is displayed, such as
  *     a battery level or progress level.  Some drawables may modify their
  *     imagery based on the current level.
- * 
+ *
  *     <li> A Drawable can perform animations by calling back to its client
  *     through the {@link Callback} interface.  All clients should support this
  *     interface (via {@link #setCallback}) so that animations will work.  A
@@ -71,7 +71,7 @@
  *     {@link android.view.View#setBackgroundDrawable(Drawable)} and
  *     {@link android.widget.ImageView}.
  * </ul>
- * 
+ *
  * Though usually not visible to the application, Drawables may take a variety
  * of forms:
  *
@@ -96,11 +96,12 @@
  * and Internationalization</a>.
  */
 public abstract class Drawable {
+    private static final Rect ZERO_BOUNDS_RECT = new Rect();
 
     private int[] mStateSet = StateSet.WILD_CARD;
     private int mLevel = 0;
     private int mChangingConfigurations = 0;
-    private Rect mBounds = new Rect();
+    private Rect mBounds = ZERO_BOUNDS_RECT;
     /*package*/ Callback mCallback = null;
     private boolean mVisible = true;
 
@@ -118,14 +119,18 @@
      */
     public void setBounds(int left, int top, int right, int bottom) {
         Rect oldBounds = mBounds;
-        
+
+        if (oldBounds == ZERO_BOUNDS_RECT) {
+            oldBounds = mBounds = new Rect();
+        }
+
         if (oldBounds.left != left || oldBounds.top != top ||
                 oldBounds.right != right || oldBounds.bottom != bottom) {
             mBounds.set(left, top, right, bottom);
             onBoundsChange(mBounds);
         }
     }
-    
+
     /**
      * Specify a bounding rectangle for the Drawable. This is where the drawable
      * will draw when its draw() method is called.
@@ -145,12 +150,12 @@
     public final void copyBounds(Rect bounds) {
         bounds.set(mBounds);
     }
-    
+
     /**
      * Return a copy of the drawable's bounds in a new Rect. This returns the
      * same values as getBounds(), but the returned object is guaranteed to not
      * be changed later by the drawable (i.e. it retains no reference to this
-     * rect). If the caller already has a Rect allocated, call copyBounds(rect)
+     * rect). If the caller already has a Rect allocated, call copyBounds(rect).
      *
      * @return A copy of the drawable's bounds
      */
@@ -163,27 +168,37 @@
      * object may be the same object stored in the drawable (though this is not
      * guaranteed), so if a persistent copy of the bounds is needed, call
      * copyBounds(rect) instead.
+     * You should also not change the object returned by this method as it may
+     * be the same object stored in the drawable.
      *
      * @return The bounds of the drawable (which may change later, so caller
-     *         beware).
+     *         beware). DO NOT ALTER the returned object as it may change the
+     *         stored bounds of this drawable.
+     *
+     * @see #copyBounds()
+     * @see #copyBounds(android.graphics.Rect) 
      */
     public final Rect getBounds() {
+        if (mBounds == ZERO_BOUNDS_RECT) {
+            mBounds = new Rect();
+        }
+
         return mBounds;
     }
 
     /**
      * Set a mask of the configuration parameters for which this drawable
      * may change, requiring that it be re-created.
-     * 
+     *
      * @param configs A mask of the changing configuration parameters, as
      * defined by {@link android.content.res.Configuration}.
-     * 
+     *
      * @see android.content.res.Configuration
      */
     public void setChangingConfigurations(int configs) {
         mChangingConfigurations = configs;
     }
-    
+
     /**
      * Return a mask of the configuration parameters for which this drawable
      * mau change, requiring that it be re-created.  The default implementation
@@ -191,23 +206,23 @@
      * {@link #setChangingConfigurations(int)} or 0 by default.  Subclasses
      * may extend this to or in the changing configurations of any other
      * drawables they hold.
-     * 
+     *
      * @return Returns a mask of the changing configuration parameters, as
      * defined by {@link android.content.res.Configuration}.
-     * 
+     *
      * @see android.content.res.Configuration
      */
     public int getChangingConfigurations() {
         return mChangingConfigurations;
     }
-    
+
     /**
      * Set to true to have the drawable dither its colors when drawn to a device
      * with fewer than 8-bits per color component. This can improve the look on
      * those devices, but can also slow down the drawing a little.
      */
     public void setDither(boolean dither) {}
-    
+
     /**
      * Set to true to have the drawable filter its bitmap when scaled or rotated
      * (for drawables that use bitmaps). If the drawable does not use bitmaps,
@@ -229,7 +244,7 @@
          * Called when the drawable needs to be redrawn.  A view at this point
          * should invalidate itself (or at least the part of itself where the
          * drawable appears).
-         * 
+         *
          * @param who The drawable that is requesting the update.
          */
         public void invalidateDrawable(Drawable who);
@@ -240,7 +255,7 @@
          * {@link android.os.Handler#postAtTime(Runnable, Object, long)} with
          * the parameters <var>(what, who, when)</var> to perform the
          * scheduling.
-         * 
+         *
          * @param who The drawable being scheduled.
          * @param what The action to execute.
          * @param when The time (in milliseconds) to run.  The timebase is
@@ -254,7 +269,7 @@
          * generally simply call
          * {@link android.os.Handler#removeCallbacks(Runnable, Object)} with
          * the parameters <var>(what, who)</var> to unschedule the drawable.
-         * 
+         *
          * @param who The drawable being unscheduled.
          * @param what The action being unscheduled.
          */
@@ -264,7 +279,7 @@
     /**
      * Bind a {@link Callback} object to this Drawable.  Required for clients
      * that want to support animated drawables.
-     * 
+     *
      * @param cb The client's Callback implementation.
      */
     public final void setCallback(Callback cb) {
@@ -275,7 +290,7 @@
      * Use the current {@link Callback} implementation to have this Drawable
      * redrawn.  Does nothing if there is no Callback attached to the
      * Drawable.
-     * 
+     *
      * @see Callback#invalidateDrawable
      */
     public void invalidateSelf()
@@ -289,10 +304,10 @@
      * Use the current {@link Callback} implementation to have this Drawable
      * scheduled.  Does nothing if there is no Callback attached to the
      * Drawable.
-     * 
+     *
      * @param what The action being scheduled.
      * @param when The time (in milliseconds) to run.
-     * 
+     *
      * @see Callback#scheduleDrawable
      */
     public void scheduleSelf(Runnable what, long when)
@@ -306,9 +321,9 @@
      * Use the current {@link Callback} implementation to have this Drawable
      * unscheduled.  Does nothing if there is no Callback attached to the
      * Drawable.
-     * 
+     *
      * @param what The runnable that you no longer want called.
-     * 
+     *
      * @see Callback#unscheduleDrawable
      */
     public void unscheduleSelf(Runnable what)
@@ -323,13 +338,13 @@
      * 255 means fully opaque.
      */
     public abstract void setAlpha(int alpha);
-    
+
     /**
      * Specify an optional colorFilter for the drawable. Pass null to remove
      * any filters.
     */
     public abstract void setColorFilter(ColorFilter cf);
-    
+
     /**
      * Specify a color and porterduff mode to be the colorfilter for this
      * drawable.
@@ -337,7 +352,7 @@
     public void setColorFilter(int color, PorterDuff.Mode mode) {
         setColorFilter(new PorterDuffColorFilter(color, mode));
     }
-    
+
     public void clearColorFilter() {
         setColorFilter(null);
     }
@@ -346,34 +361,34 @@
      * Indicates whether this view will change its appearance based on state.
      * Clients can use this to determine whether it is necessary to calculate
      * their state and call setState.
-     * 
+     *
      * @return True if this view changes its appearance based on state, false
      *         otherwise.
-     * 
+     *
      * @see #setState(int[])
      */
     public boolean isStateful() {
         return false;
     }
-    
+
     /**
      * Specify a set of states for the drawable. These are use-case specific,
      * so see the relevant documentation. As an example, the background for
      * widgets like Button understand the following states:
      * [{@link android.R.attr#state_focused},
      *  {@link android.R.attr#state_pressed}].
-     * 
+     *
      * <p>If the new state you are supplying causes the appearance of the
      * Drawable to change, then it is responsible for calling
      * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
      * true will be returned from this function.
-     * 
+     *
      * <p>Note: The Drawable holds a reference on to <var>stateSet</var>
      * until a new state array is given to it, so you must not modify this
      * array during that time.</p>
-     * 
+     *
      * @param stateSet The new set of states to be displayed.
-     * 
+     *
      * @return Returns true if this change in state has caused the appearance
      * of the Drawable to change (hence requiring an invalidate), otherwise
      * returns false.
@@ -396,7 +411,7 @@
     public int[] getState() {
         return mStateSet;
     }
-    
+
     /**
      * @return The current drawable that will be used by this drawable. For simple drawables, this
      *         is just the drawable itself. For drawables that change state like
@@ -416,9 +431,9 @@
      * Drawable to change, then it is responsible for calling
      * {@link #invalidateSelf} in order to have itself redrawn, <em>and</em>
      * true will be returned from this function.
-     * 
+     *
      * @param level The new level, from 0 (minimum) to 10000 (maximum).
-     * 
+     *
      * @return Returns true if this change in level has caused the appearance
      * of the Drawable to change (hence requiring an invalidate), otherwise
      * returns false.
@@ -529,7 +544,7 @@
      * region; subclasses can optionally override this to return an actual
      * Region if they want to supply this optimization information, but it is
      * not required that they do so.
-     * 
+     *
      * @return Returns null if the Drawables has no transparent region to
      * report, else a Region holding the parts of the Drawable's bounds that
      * are transparent.
@@ -537,11 +552,11 @@
     public Region getTransparentRegion() {
         return null;
     }
-    
+
     /**
      * Override this in your subclass to change appearance if you recognize the
      * specified state.
-     * 
+     *
      * @return Returns true if the state change has caused the appearance of
      * the Drawable to change (that is, it needs to be drawn), else false
      * if it looks the same and there is no need to redraw it since its
@@ -577,13 +592,13 @@
     public int getIntrinsicHeight() {
         return -1;
     }
-    
+
     /**
      * Returns the minimum width suggested by this Drawable. If a View uses this
      * Drawable as a background, it is suggested that the View use at least this
      * value for its width. (There will be some scenarios where this will not be
      * possible.) This value should INCLUDE any padding.
-     * 
+     *
      * @return The minimum width suggested by this Drawable. If this Drawable
      *         doesn't have a suggested minimum width, 0 is returned.
      */
@@ -597,7 +612,7 @@
      * Drawable as a background, it is suggested that the View use at least this
      * value for its height. (There will be some scenarios where this will not be
      * possible.) This value should INCLUDE any padding.
-     * 
+     *
      * @return The minimum height suggested by this Drawable. If this Drawable
      *         doesn't have a suggested minimum height, 0 is returned.
      */
@@ -605,7 +620,7 @@
         final int intrinsicHeight = getIntrinsicHeight();
         return intrinsicHeight > 0 ? intrinsicHeight : 0;
     }
-    
+
     /**
      * Return in padding the insets suggested by this Drawable for placing
      * content inside the drawable's bounds. Positive values move toward the
@@ -643,7 +658,7 @@
 
     /**
      * Create a drawable from an inputstream
-     * 
+     *
      * @hide pending API council approval
      */
     public static Drawable createFromResourceStream(Resources res, TypedValue value,
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 7164b78..6aa40d00 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -312,7 +312,6 @@
 
             bool processAudioBuffer(const sp<ClientRecordThread>& thread);
 
-    sp<IAudioFlinger>       mAudioFlinger;
     sp<IAudioRecord>        mAudioRecord;
     sp<IMemory>             mCblkMemory;
     sp<ClientRecordThread>  mClientRecordThread;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 7645978..ba0467c 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -383,7 +383,6 @@
 
             bool processAudioBuffer(const sp<AudioTrackThread>& thread);
 
-    sp<IAudioFlinger>       mAudioFlinger;
     sp<IAudioTrack>         mAudioTrack;
     sp<IMemory>             mCblkMemory;
     sp<AudioTrackThread>    mAudioTrackThread;
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index e593fea..fd851d9 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -78,8 +78,7 @@
 {
 public:
             // construct a camera client from an existing remote
-            Camera(const sp<ICamera>& camera);
-
+    static  sp<Camera>  create(const sp<ICamera>& camera);
     static  sp<Camera>  connect();
                         ~Camera();
             void        init();
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index d01d83f..9b8c302 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -988,119 +988,225 @@
         return diffs;
     }
     
-    // Return true if 'this' is more specific than 'o'.  Optionally, if
-    // 'requested' is null, then they will also be compared against the
-    // requested configuration and true will only be returned if 'this'
-    // is a better candidate than 'o' for the configuration.  This assumes that
-    // match() has already been used to remove any configurations that don't
-    // match the requested configuration at all; if they are not first filtered,
-    // non-matching results can be considered better than matching ones.
+    // Return true if 'this' is more specific than 'o'.
     inline bool
-    isBetterThan(const ResTable_config& o, const ResTable_config* requested = NULL) const {
+    isMoreSpecificThan(const ResTable_config& o) const {
         // The order of the following tests defines the importance of one
         // configuration parameter over another.  Those tests first are more
         // important, trumping any values in those following them.
-        if (imsi != 0 && (!requested || requested->imsi != 0)) {
-            if (mcc != 0 && (!requested || requested->mcc != 0)) {
-                if (o.mcc == 0) {
-                    return true;
-                }
+        if (imsi || o.imsi) {
+            if (mcc != o.mcc) {
+                if (!mcc) return false;
+                if (!o.mcc) return true;
             }
-            if (mnc != 0 && (!requested || requested->mnc != 0)) {
-                if (o.mnc == 0) {
-                    return true;
-                }
+
+            if (mnc != o.mnc) {
+                if (!mnc) return false;
+                if (!o.mnc) return true;
             }
         }
-        if (locale != 0 && (!requested || requested->locale != 0)) {
-            if (language[0] != 0 && (!requested || requested->language[0] != 0)) {
-                if (o.language[0] == 0) {
-                    return true;
-                }
+
+        if (locale || o.locale) {
+            if (language[0] != o.language[0]) {
+                if (!language[0]) return false;
+                if (!o.language[0]) return true;
             }
-            if (country[0] != 0 && (!requested || requested->country[0] != 0)) {
-                if (o.country[0] == 0) {
-                    return true;
-                }
+
+            if (country[0] != o.country[0]) {
+                if (!country[0]) return false;
+                if (!o.country[0]) return true;
             }
         }
-        if (screenType != 0 && (!requested || requested->screenType != 0)) {
-            if (orientation != 0 && (!requested || requested->orientation != 0)) {
-                if (o.orientation == 0) {
-                    return true;
-                }
+
+        if (screenType || o.screenType) {
+            if (orientation != o.orientation) {
+                if (!orientation) return false;
+                if (!o.orientation) return true;
             }
-            if (density != 0 && (!requested || requested->density != 0)) {
-                if (o.density == 0) {
-                    return true;
-                }
-            }
-            if (touchscreen != 0 && (!requested || requested->touchscreen != 0)) {
-                if (o.touchscreen == 0) {
-                    return true;
-                }
+
+            // density is never 'more specific'
+            // as the default just equals 160
+
+            if (touchscreen != o.touchscreen) {
+                if (!touchscreen) return false;
+                if (!o.touchscreen) return true;
             }
         }
-        if (input != 0 && (!requested || requested->input != 0)) {
-            const int keysHidden = inputFlags&MASK_KEYSHIDDEN;
-            const int reqKeysHidden = requested
-                    ? requested->inputFlags&MASK_KEYSHIDDEN : 0;
-            if (keysHidden != 0 && reqKeysHidden != 0) {
-                const int oKeysHidden = o.inputFlags&MASK_KEYSHIDDEN;
-                //LOGI("isBetterThan keysHidden: cur=%d, given=%d, config=%d\n",
-                //        keysHidden, oKeysHidden, reqKeysHidden);
-                if (oKeysHidden == 0) {
-                    //LOGI("Better because 0!");
-                    return true;
-                }
-                // For compatibility, we count KEYSHIDDEN_NO as being
-                // the same as KEYSHIDDEN_SOFT.  Here we disambiguate these
-                // may making an exact match more specific.
-                if (keysHidden == reqKeysHidden && oKeysHidden != reqKeysHidden) {
-                    // The current configuration is an exact match, and
-                    // the given one is not, so the current one is better.
-                    //LOGI("Better because other not same!");
-                    return true;
-                }
+
+        if (input || o.input) {
+            if (inputFlags != o.inputFlags) {
+                if (!(inputFlags & MASK_KEYSHIDDEN)) return false;
+                if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
             }
-            if (keyboard != 0 && (!requested || requested->keyboard != 0)) {
-                if (o.keyboard == 0) {
-                    return true;
-                }
+
+            if (keyboard != o.keyboard) {
+                if (!keyboard) return false;
+                if (!o.keyboard) return true;
             }
-            if (navigation != 0 && (!requested || requested->navigation != 0)) {
-                if (o.navigation == 0) {
-                    return true;
-                }
+
+            if (navigation != o.navigation) {
+                if (!navigation) return false;
+                if (!o.navigation) return true;
             }
         }
-        if (screenSize != 0 && (!requested || requested->screenSize != 0)) {
-            if (screenWidth != 0 && (!requested || requested->screenWidth != 0)) {
-                if (o.screenWidth == 0) {
-                    return true;
-                }
+
+        if (screenSize || o.screenSize) {
+            if (screenWidth != o.screenWidth) {
+                if (!screenWidth) return false;
+                if (!o.screenWidth) return true;
             }
-            if (screenHeight != 0 && (!requested || requested->screenHeight != 0)) {
-                if (o.screenHeight == 0) {
-                    return true;
-                }
+
+            if (screenHeight != o.screenHeight) {
+                if (!screenHeight) return false;
+                if (!o.screenHeight) return true;
             }
         }
-        if (version != 0 && (!requested || requested->version != 0)) {
-            if (sdkVersion != 0 && (!requested || requested->sdkVersion != 0)) {
-                if (o.sdkVersion == 0) {
-                    return true;
-                }
+
+        if (version || o.version) {
+            if (sdkVersion != o.sdkVersion) {
+                if (!sdkVersion) return false;
+                if (!o.sdkVersion) return true;
             }
-            if (minorVersion != 0 && (!requested || requested->minorVersion != 0)) {
-                if (o.minorVersion == 0) {
-                    return true;
-                }
+
+            if (minorVersion != o.minorVersion) {
+                if (!minorVersion) return false;
+                if (!o.minorVersion) return true;
             }
         }
         return false;
     }
-    
+
+    // Return true if 'this' is a better match than 'o' for the 'requested'
+    // configuration.  This assumes that match() has already been used to
+    // remove any configurations that don't match the requested configuration
+    // at all; if they are not first filtered, non-matching results can be
+    // considered better than matching ones.
+    // The general rule per attribute: if the request cares about an attribute
+    // (it normally does), if the two (this and o) are equal it's a tie.  If
+    // they are not equal then one must be generic because only generic and
+    // '==requested' will pass the match() call.  So if this is not generic,
+    // it wins.  If this IS generic, o wins (return false).
+    inline bool
+    isBetterThan(const ResTable_config& o,
+            const ResTable_config* requested) const {
+        if (requested) {
+            if (imsi || o.imsi) {
+                if ((mcc != o.mcc) && requested->mcc) {
+                    return (mcc);
+                }
+
+                if ((mnc != o.mnc) && requested->mnc) {
+                    return (mnc);
+                }
+            }
+
+            if (locale || o.locale) {
+                if ((language[0] != o.language[0]) && requested->language[0]) {
+                    return (language[0]);
+                }
+
+                if ((country[0] != o.country[0]) && requested->country[0]) {
+                    return (country[0]);
+                }
+            }
+
+            if (screenType || o.screenType) {
+                if ((orientation != o.orientation) && requested->orientation) {
+                    return (orientation);
+                }
+
+                if (density != o.density) {
+                    // density is tough.  Any density is potentially useful
+                    // because the system will scale it.  Scaling down
+                    // is generally better than scaling up.
+                    // Default density counts as 160dpi (the system default)
+                    // TODO - remove 160 constants
+                    int h = (density?density:160);
+                    int l = (o.density?o.density:160);
+                    bool bImBigger = true;
+                    if (l > h) {
+                        int t = h;
+                        h = l;
+                        l = t;
+                        bImBigger = false;
+                    }
+ 
+                    int reqValue = (requested->density?requested->density:160);
+                    if (reqValue >= h) {
+                        // requested value higher than both l and h, give h
+                        return bImBigger;
+                    }
+                    if (l >= reqValue) {
+                        // requested value lower than both l and h, give l
+                        return !bImBigger;
+                    }
+                    // saying that scaling down is 2x better than up
+                    if (((2 * l) - reqValue) * h > reqValue * reqValue) {
+                        return !bImBigger;
+                    } else { 
+                        return bImBigger;
+                    }
+                }
+
+                if ((touchscreen != o.touchscreen) && requested->touchscreen) {
+                    return (touchscreen);
+                }
+            }
+
+            if (input || o.input) {
+                const int keysHidden = inputFlags & MASK_KEYSHIDDEN;
+                const int oKeysHidden = o.inputFlags & MASK_KEYSHIDDEN;
+                if (keysHidden != oKeysHidden) {
+                    const int reqKeysHidden =
+                            requested->inputFlags & MASK_KEYSHIDDEN;
+                    if (reqKeysHidden) {
+
+                        if (!keysHidden) return false;
+                        if (!oKeysHidden) return true;
+                        // For compatibility, we count KEYSHIDDEN_NO as being
+                        // the same as KEYSHIDDEN_SOFT.  Here we disambiguate
+                        // these by making an exact match more specific.
+                        if (reqKeysHidden == keysHidden) return true;
+                        if (reqKeysHidden == oKeysHidden) return false;
+                    }
+                }
+
+                if ((keyboard != o.keyboard) && requested->keyboard) {
+                    return (keyboard);
+                }
+
+                if ((navigation != o.navigation) && requested->navigation) {
+                    return (navigation);
+                }
+            }
+
+            if (screenSize || o.screenSize) {
+                if ((screenWidth != o.screenWidth) && requested->screenWidth) {
+                    return (screenWidth);
+                }
+
+                if ((screenHeight != o.screenHeight) &&
+                        requested->screenHeight) {
+                    return (screenHeight);
+                }
+            }
+
+            if (version || o.version) {
+                if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) {
+                    return (sdkVersion);
+                }
+
+                if ((minorVersion != o.minorVersion) &&
+                        requested->minorVersion) {
+                    return (minorVersion);
+                }
+            }
+
+            return false;
+        }
+        return isMoreSpecificThan(o);
+    }
+
     // Return true if 'this' can be considered a match for the parameters in 
     // 'settings'.
     // Note this is asymetric.  A default piece of data will match every request
@@ -1137,8 +1243,7 @@
                 && orientation != settings.orientation) {
                 return false;
             }
-            // Density not taken into account, always match, no matter what
-            // density is specified for the resource
+            // density always matches - we can scale it.  See isBetterThan
             if (settings.touchscreen != 0 && touchscreen != 0
                 && touchscreen != settings.touchscreen) {
                 return false;
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 8d8d46a..b320915 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -79,6 +79,13 @@
     ANDROID_PRIORITY_LESS_FAVORABLE = +1,
 };
 
+enum {
+    ANDROID_TGROUP_DEFAULT          = 0,
+    ANDROID_TGROUP_BG_NONINTERACT   = 1,
+    ANDROID_TGROUP_FG_BOOST         = 2,
+    ANDROID_TGROUP_MAX              = ANDROID_TGROUP_FG_BOOST,
+};
+
 // Create and run a new thread.
 extern int androidCreateThread(android_thread_func_t, void *);
 
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index d11e13a..b56221f 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -651,27 +651,30 @@
         return BAD_VALUE;
     }
 
-    mHardwareMixerThread->setStreamVolume(stream, value);
-#ifdef WITH_A2DP
-    mA2dpMixerThread->setStreamVolume(stream, value);
-#endif
-
     status_t ret = NO_ERROR;
     if (stream == AudioSystem::VOICE_CALL ||
         stream == AudioSystem::BLUETOOTH_SCO) {
-        
+        float hwValue;
         if (stream == AudioSystem::VOICE_CALL) {
-            value = (float)AudioSystem::logToLinear(value)/100.0f;
+            hwValue = (float)AudioSystem::logToLinear(value)/100.0f;
+            // offset value to reflect actual hardware volume that never reaches 0
+            // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
+            value = 0.01 + 0.99 * value;
         } else { // (type == AudioSystem::BLUETOOTH_SCO)
-            value = 1.0f;
+            hwValue = 1.0f;
         }
 
         AutoMutex lock(mHardwareLock);
         mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
-        ret = mAudioHardware->setVoiceVolume(value);
+        ret = mAudioHardware->setVoiceVolume(hwValue);
         mHardwareStatus = AUDIO_HW_IDLE;
     }
 
+    mHardwareMixerThread->setStreamVolume(stream, value);
+#ifdef WITH_A2DP
+    mA2dpMixerThread->setStreamVolume(stream, value);
+#endif
+
     return ret;
 }
 
@@ -709,7 +712,14 @@
     if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return 0.0f;
     }
-    return mHardwareMixerThread->streamVolume(stream);
+    
+    float volume = mHardwareMixerThread->streamVolume(stream); 
+    // remove correction applied by setStreamVolume()
+    if (stream == AudioSystem::VOICE_CALL) {
+        volume = (volume - 0.01) / 0.99 ;
+    }
+    
+    return volume;
 }
 
 bool AudioFlinger::streamMute(int stream) const
@@ -812,17 +822,12 @@
                 if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
                     LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
                     mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
-                    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-                    mAudioHardware->setMasterVolume(0);
                     usleep(mHardwareMixerThread->latency()*1000);
                     mHardwareStatus = AUDIO_HW_SET_ROUTING;
                     mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
                     mHardwareStatus = AUDIO_HW_IDLE;
                     // delay track start so that audio hardware has time to siwtch routes
                     usleep(kStartSleepTime);
-                    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
-                    mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume());
-                    mHardwareStatus = AUDIO_HW_IDLE;
                 }
                 mForcedRoute = AudioSystem::ROUTE_SPEAKER;
             }
@@ -1480,18 +1485,6 @@
     return status;
 }
 
-// removeTrack_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name)
-{
-    sp<Track> t = track.promote();
-    if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
-        t->reset();
-        deleteTrackName_l(name);
-        removeActiveTrack_l(track);
-        mAudioFlinger->mWaitWorkCV.broadcast();
-    }
-}
-
 // destroyTrack_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track)
 {
@@ -1697,7 +1690,7 @@
 
     // Check validity of returned pointer in case the track control block would have been corrupted.
     if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || 
-            cblk->channels == 2 && ((unsigned long)bufferStart & 3) ) {
+        (cblk->channels == 2 && ((unsigned long)bufferStart & 3))) {
         LOGE("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
                 server %d, serverBase %d, user %d, userBase %d, channels %d",
                 bufferStart, bufferEnd, mBuffer, mBufferEnd,
@@ -1733,7 +1726,6 @@
     wp<Track> weak(this); // never create a strong ref from the dtor
     Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     mState = TERMINATED;
-    mMixerThread->removeTrack_l(weak, mName);
 }
 
 void AudioFlinger::MixerThread::Track::destroy()
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index db5cc74..c7ca9ec 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -501,7 +501,6 @@
         MixerThread& operator = (const MixerThread&);
   
         status_t    addTrack_l(const sp<Track>& track);
-        void        removeTrack_l(wp<Track> track, int name);
         void        destroyTrack_l(const sp<Track>& track);
         int         getTrackName_l();
         void        deleteTrackName_l(int name);
diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/libs/audioflinger/AudioHardwareInterface.cpp
index ac76a19..cc1bd8f 100644
--- a/libs/audioflinger/AudioHardwareInterface.cpp
+++ b/libs/audioflinger/AudioHardwareInterface.cpp
@@ -53,7 +53,7 @@
     "EARPIECE ",
     "SPEAKER ",
     "BLUETOOTH ",
-    "HEADSET "
+    "HEADSET ",
     "BLUETOOTH_A2DP "
 };
 static const char* routeNone = "NONE";
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
index eb75f99..7168bf2 100644
--- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
@@ -573,7 +573,11 @@
 
 sp<GPUHardwareInterface> GPUFactory::getGPU()
 {
-    return new GPUHardware();
+    sp<GPUHardwareInterface> gpu;
+    if (access("/dev/hw3d", F_OK) == 0) {
+        gpu = new GPUHardware();
+    }
+    return gpu;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index f65d669..96395a8 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -108,7 +108,7 @@
     // we always force a 4-byte aligned bpr.
     uint32_t alignment = 1;
 
-    if (flags & ISurfaceComposer::eGPU) {
+    if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) {
         // FIXME: this value should come from the h/w
         alignment = 8; 
         // FIXME: this is msm7201A specific, as its GPU only supports
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index de64f55..167a59b 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -241,6 +241,9 @@
 status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback,
         gpu_info_t* gpu)
 {
+    if (mGPU == 0)
+        return INVALID_OPERATION;
+
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     status_t err = mGPU->request(pid, callback, gpu);
@@ -249,6 +252,9 @@
 
 status_t SurfaceFlinger::revokeGPU()
 {
+    if (mGPU == 0)
+        return INVALID_OPERATION;
+
     return mGPU->friendlyRevoke();
 }
 
@@ -1600,10 +1606,14 @@
             }
             return NO_ERROR;
             case 1005: // ask GPU revoke
-                mGPU->friendlyRevoke();
+                if (mGPU != 0) {
+                    mGPU->friendlyRevoke();
+                }
                 return NO_ERROR;
             case 1006: // revoke GPU
-                mGPU->unconditionalRevoke();
+                if (mGPU != 0) {
+                    mGPU->unconditionalRevoke();
+                }
                 return NO_ERROR;
             case 1007: // set mFreezeCount
                 mFreezeCount = data.readInt32();
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
index 0ccd71f..238c602 100644
--- a/libs/surfaceflinger/VRamHeap.cpp
+++ b/libs/surfaceflinger/VRamHeap.cpp
@@ -98,7 +98,7 @@
         }
     }
 
-    if (flags & ISurfaceComposer::eGPU) {
+    if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) {
         // FIXME: this is msm7201A specific, where gpu surfaces may not be secure
         if (!(flags & ISurfaceComposer::eSecure)) {
             // if GPU doesn't work, we try eHardware
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index b3cbda1..41577c4 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -64,15 +64,22 @@
     init();
 }
 
-Camera::Camera(const sp<ICamera>& camera)
+// construct a camera client from an existing camera remote
+sp<Camera> Camera::create(const sp<ICamera>& camera)
 {
-    init();
-    // connect this client to existing camera remote
-    if (camera->connect(this) == NO_ERROR) {
-        mStatus = NO_ERROR;
-        mCamera = camera;
-        camera->asBinder()->linkToDeath(this);
+     LOGV("create");
+     if (camera == 0) {
+         LOGE("camera remote is a NULL pointer");
+         return 0;
+     }
+
+    sp<Camera> c = new Camera();
+    if (camera->connect(c) == NO_ERROR) {
+        c->mStatus = NO_ERROR;
+        c->mCamera = camera;
+        camera->asBinder()->linkToDeath(c);
     }
+    return c;
 }
 
 void Camera::init()
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 2ad3bfe..3d12dca 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -1820,7 +1820,7 @@
             }
         }
         
-        if (bestPackage != NULL && bestItem.isBetterThan(thisConfig)) {
+        if (bestPackage != NULL && bestItem.isMoreSpecificThan(thisConfig)) {
             continue;
         }
         
diff --git a/location/data/Android.mk b/location/data/Android.mk
deleted file mode 100644
index 794e6c7..0000000
--- a/location/data/Android.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Install 3 sample gps files (nmea, location, and properties)
-# for use with the SDK 
-#
-
-# where to install the sample files on the device
-# 
-local_target_dir := $(TARGET_OUT_DATA)/location
-
-########################
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := nmea
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(local_target_dir)/gps
-
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-########################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := location
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(local_target_dir)/gps
-
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-########################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := properties
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(local_target_dir)/gps
-
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
-
-########################
diff --git a/location/data/kml/kml b/location/data/kml/kml
deleted file mode 100644
index e1d98b8..0000000
--- a/location/data/kml/kml
+++ /dev/null
@@ -1,2 +0,0 @@
-<coordinates>003405.000,3725.3433,12205.7921 003405.000,3725.3433,12205.7921</coordinates>
-<coordinates>003405.000,3725.3433,12205.7921 003405.000,3725.3433,12205.7921</coordinates>
diff --git a/location/data/kml/properties b/location/data/kml/properties
deleted file mode 100644
index 42d319f..0000000
--- a/location/data/kml/properties
+++ /dev/null
@@ -1,11 +0,0 @@
-requiresNetwork false
-requiresSatellite false
-requiresCell true
-hasMonetaryCost false
-supportsAltitude true
-supportsBearing false
-supportsSpeed true
-repeat true
-accuracy 2
-powerRequirement 2
-trackSpeed 100
diff --git a/location/data/location b/location/data/location
deleted file mode 100644
index 1c0c986..0000000
--- a/location/data/location
+++ /dev/null
@@ -1 +0,0 @@
-gps,1193789209,37.42238666666666666666,-122.096535,0,0,0
diff --git a/location/data/nmea b/location/data/nmea
deleted file mode 100644
index 1b6b45b..0000000
--- a/location/data/nmea
+++ /dev/null
@@ -1,162 +0,0 @@
-$GPRMC,003350.000,A,3725.3432,N,12205.7921,W,0.06,151.59,061007,,,D*7F
-$GPRMC,003355.000,A,3725.3430,N,12205.7920,W,0.18,109.49,061007,,,D*7A
-$GPRMC,003400.000,A,3725.3433,N,12205.7921,W,0.02,227.11,061007,,,D*76
-$GPRMC,003405.000,A,3725.3433,N,12205.7921,W,0.17,103.32,061007,,,D*73
-$GPRMC,003410.000,A,3725.3431,N,12205.7921,W,0.22,167.43,061007,,,D*77
-$GPRMC,003415.000,A,3725.3427,N,12205.7921,W,0.23,246.49,061007,,,D*7E
-$GPRMC,003420.000,A,3725.3423,N,12205.7917,W,0.16,74.88,061007,,,D*41
-$GPRMC,003425.000,A,3725.3426,N,12205.7919,W,0.05,124.94,061007,,,D*74
-$GPRMC,003430.000,A,3725.3429,N,12205.7919,W,0.15,77.12,061007,,,D*47
-$GPRMC,003435.000,A,3725.3432,N,12205.7921,W,0.07,94.72,061007,,,D*4B
-$GPRMC,003440.000,A,3725.3436,N,12205.7921,W,0.13,336.72,061007,,,D*73
-$GPRMC,003445.000,A,3725.3440,N,12205.7953,W,2.72,278.90,061007,,,D*70
-$GPRMC,003450.000,A,3725.3442,N,12205.7977,W,2.02,164.81,061007,,,D*79
-$GPRMC,003455.000,A,3725.3380,N,12205.8008,W,8.28,200.23,061007,,,D*70
-$GPRMC,003500.000,A,3725.3207,N,12205.8057,W,14.04,189.77,061007,,,D*45
-$GPRMC,003505.000,A,3725.3032,N,12205.8094,W,11.67,205.32,061007,,,D*4D
-$GPRMC,003510.000,A,3725.2988,N,12205.8295,W,17.09,271.31,061007,,,D*4D
-$GPRMC,003515.000,A,3725.3005,N,12205.8672,W,25.02,273.74,061007,,,D*41
-$GPRMC,003520.000,A,3725.3030,N,12205.9159,W,29.84,273.27,061007,,,D*4A
-$GPRMC,003525.000,A,3725.3061,N,12205.9683,W,28.20,274.26,061007,,,D*42
-$GPRMC,003530.000,A,3725.3092,N,12206.0150,W,25.25,274.96,061007,,,D*4A
-$GPRMC,003535.000,A,3725.3124,N,12206.0503,W,12.55,276.56,061007,,,D*4C
-$GPRMC,003540.000,A,3725.3135,N,12206.0637,W,3.99,272.32,061007,,,D*7C
-$GPRMC,003545.000,A,3725.3140,N,12206.0701,W,2.80,273.59,061007,,,D*7A
-$GPRMC,003550.000,A,3725.3143,N,12206.0734,W,0.84,266.99,061007,,,D*75
-$GPRMC,003555.000,A,3725.3142,N,12206.0731,W,0.13,157.63,061007,,,D*7E
-$GPRMC,003600.000,A,3725.3142,N,12206.0729,W,0.16,239.76,061007,,,D*7E
-$GPRMC,003605.000,A,3725.3141,N,12206.0726,W,0.15,199.57,061007,,,D*7E
-$GPRMC,003610.000,A,3725.3141,N,12206.0724,W,0.07,161.75,061007,,,D*7C
-$GPRMC,003615.000,A,3725.3141,N,12206.0721,W,0.14,171.95,061007,,,D*71
-$GPRMC,003620.000,A,3725.3141,N,12206.0718,W,0.12,188.87,061007,,,D*7E
-$GPRMC,003625.000,A,3725.3141,N,12206.0716,W,0.14,164.43,061007,,,D*79
-$GPRMC,003630.000,A,3725.3141,N,12206.0714,W,0.10,186.09,061007,,,D*79
-$GPRMC,003635.000,A,3725.3142,N,12206.0716,W,0.09,224.65,061007,,,D*74
-$GPRMC,003640.000,A,3725.3142,N,12206.0716,W,0.09,187.23,061007,,,D*7E
-$GPRMC,003645.000,A,3725.3143,N,12206.0716,W,0.14,229.41,061007,,,D*75
-$GPRMC,003650.000,A,3725.3143,N,12206.0716,W,0.14,195.40,061007,,,D*74
-$GPRMC,003655.000,A,3725.3143,N,12206.0716,W,0.51,267.41,061007,,,D*7F
-$GPRMC,003700.000,A,3725.3148,N,12206.0813,W,9.83,274.54,061007,,,D*7F
-$GPRMC,003705.000,A,3725.3247,N,12206.0930,W,15.25,357.95,061007,,,D*4A
-$GPRMC,003710.000,A,3725.3558,N,12206.0907,W,27.03,4.83,061007,,,D*44
-$GPRMC,003715.000,A,3725.3993,N,12206.0862,W,34.76,4.78,061007,,,D*4C
-$GPRMC,003720.000,A,3725.4514,N,12206.0802,W,39.38,5.62,061007,,,D*45
-$GPRMC,003725.000,A,3725.5072,N,12206.0756,W,38.59,358.11,061007,,,D*43
-$GPRMC,003730.000,A,3725.5581,N,12206.0877,W,36.13,344.59,061007,,,D*43
-$GPRMC,003735.000,A,3725.6078,N,12206.1038,W,36.78,348.75,061007,,,D*4B
-$GPRMC,003740.000,A,3725.6604,N,12206.1021,W,37.66,14.75,061007,,,D*78
-$GPRMC,003745.000,A,3725.7064,N,12206.0817,W,32.70,20.79,061007,,,D*79
-$GPRMC,003750.000,A,3725.7482,N,12206.0613,W,31.70,20.73,061007,,,D*72
-$GPRMC,003755.000,A,3725.7841,N,12206.0458,W,25.05,16.94,061007,,,D*72
-$GPRMC,003800.000,A,3725.8137,N,12206.0368,W,16.01,11.76,061007,,,D*71
-$GPRMC,003805.000,A,3725.8266,N,12206.0341,W,2.45,9.89,061007,,,D*74
-$GPRMC,003810.000,A,3725.8273,N,12206.0340,W,1.42,8.42,061007,,,D*77
-$GPRMC,003815.000,A,3725.8287,N,12206.0340,W,3.02,8.77,061007,,,D*79
-$GPRMC,003820.000,A,3725.8402,N,12206.0321,W,11.90,7.87,061007,,,D*4B
-$GPRMC,003825.000,A,3725.8520,N,12206.0422,W,12.90,274.31,061007,,,D*43
-$GPRMC,003830.000,A,3725.8386,N,12206.0610,W,17.45,193.03,061007,,,D*48
-$GPRMC,003835.000,A,3725.8082,N,12206.0693,W,25.06,193.69,061007,,,D*4B
-$GPRMC,003840.000,A,3725.7732,N,12206.0836,W,24.74,216.89,061007,,,D*4F
-$GPRMC,003845.000,A,3725.7672,N,12206.1208,W,23.64,296.05,061007,,,D*43
-$GPRMC,003850.000,A,3725.7944,N,12206.1530,W,30.80,314.88,061007,,,D*47
-$GPRMC,003855.000,A,3725.8272,N,12206.1893,W,31.57,318.18,061007,,,D*49
-$GPRMC,003900.000,A,3725.8605,N,12206.2264,W,31.13,318.65,061007,,,D*47
-$GPRMC,003905.000,A,3725.8939,N,12206.2625,W,32.39,318.52,061007,,,A*49
-$GPRMC,003910.000,A,3725.9297,N,12206.2994,W,33.37,319.89,061007,,,A*4E
-$GPRMC,003915.000,A,3725.9666,N,12206.3378,W,34.92,320.36,061007,,,A*4E
-$GPRMC,003920.000,A,3726.0048,N,12206.3777,W,35.91,319.96,061007,,,A*41
-$GPRMC,003925.000,A,3726.0439,N,12206.4186,W,36.78,319.98,061007,,,A*43
-$GPRMC,003930.000,A,3726.0837,N,12206.4602,W,37.26,320.27,061007,,,A*4A
-$GPRMC,003935.000,A,3726.1240,N,12206.5024,W,37.88,320.27,061007,,,A*43
-$GPRMC,003940.000,A,3726.1647,N,12206.5449,W,37.95,319.99,061007,,,A*4E
-$GPRMC,003945.000,A,3726.2055,N,12206.5874,W,37.24,320.06,061007,,,A*49
-$GPRMC,003950.000,A,3726.2438,N,12206.6274,W,34.50,320.25,061007,,,A*4A
-$GPRMC,003955.000,A,3726.2805,N,12206.6661,W,34.75,319.90,061007,,,A*4E
-$GPRMC,004000.000,A,3726.3181,N,12206.7054,W,35.63,320.23,061007,,,A*41
-$GPRMC,004005.000,A,3726.3570,N,12206.7462,W,36.84,320.29,061007,,,A*4F
-$GPRMC,004010.000,A,3726.3961,N,12206.7872,W,35.85,320.09,061007,,,A*4A
-$GPRMC,004015.000,A,3726.4343,N,12206.8276,W,36.84,320.17,061007,,,A*4E
-$GPRMC,004020.000,A,3726.4759,N,12206.8712,W,40.53,320.65,061007,,,A*4E
-$GPRMC,004025.000,A,3726.5190,N,12206.9164,W,39.54,320.13,061007,,,A*47
-$GPRMC,004030.000,A,3726.5607,N,12206.9605,W,38.84,319.99,061007,,,A*4E
-$GPRMC,004035.000,A,3726.6010,N,12207.0030,W,36.82,320.30,061007,,,A*41
-$GPRMC,004040.000,A,3726.6413,N,12207.0416,W,35.63,328.90,061007,,,A*4A
-$GPRMC,004045.000,A,3726.6861,N,12207.0652,W,35.49,342.93,061007,,,A*43
-$GPRMC,004050.000,A,3726.7346,N,12207.0842,W,37.15,342.57,061007,,,A*44
-$GPRMC,004055.000,A,3726.7834,N,12207.1033,W,36.68,342.14,061007,,,A*4C
-$GPRMC,004100.000,A,3726.8328,N,12207.1225,W,36.73,343.04,061007,,,D*4E
-$GPRMC,004105.000,A,3726.8795,N,12207.1405,W,33.44,343.08,061007,,,D*40
-$GPRMC,004110.000,A,3726.9211,N,12207.1570,W,28.00,343.17,061007,,,D*4B
-$GPRMC,004115.000,A,3726.9507,N,12207.1678,W,18.59,345.92,061007,,,D*41
-$GPRMC,004120.000,A,3726.9639,N,12207.1722,W,3.24,343.37,061007,,,D*7E
-$GPRMC,004125.000,A,3726.9641,N,12207.1725,W,0.21,154.73,061007,,,D*71
-$GPRMC,004130.000,A,3726.9634,N,12207.1722,W,0.16,105.89,061007,,,D*75
-$GPRMC,004135.000,A,3726.9630,N,12207.1720,W,0.04,133.97,061007,,,D*7F
-$GPRMC,004140.000,A,3726.9627,N,12207.1718,W,0.16,107.47,061007,,,D*79
-$GPRMC,004145.000,A,3726.9625,N,12207.1716,W,0.14,148.73,061007,,,D*7E
-$GPRMC,004150.000,A,3726.9621,N,12207.1715,W,0.09,142.18,061007,,,D*76
-$GPRMC,004155.000,A,3726.9620,N,12207.1714,W,0.10,95.75,061007,,,D*4B
-$GPRMC,004200.000,A,3726.9618,N,12207.1714,W,0.07,135.28,061007,,,D*76
-$GPRMC,004205.000,A,3726.9617,N,12207.1713,W,0.14,86.20,061007,,,D*48
-$GPRMC,004210.000,A,3726.9616,N,12207.1713,W,0.05,130.34,061007,,,D*74
-$GPRMC,004215.000,A,3726.9614,N,12207.1714,W,0.08,120.53,061007,,,D*79
-$GPRMC,004220.000,A,3726.9612,N,12207.1714,W,0.09,147.27,061007,,,D*7A
-$GPRMC,004225.000,A,3726.9612,N,12207.1715,W,0.12,118.20,061007,,,D*79
-$GPRMC,004230.000,A,3726.9612,N,12207.1714,W,0.12,90.61,061007,,,D*48
-$GPRMC,004235.000,A,3726.9612,N,12207.1715,W,0.10,156.15,061007,,,D*76
-$GPRMC,004240.000,A,3726.9612,N,12207.1715,W,0.13,104.74,061007,,,D*77
-$GPRMC,004245.000,A,3726.9617,N,12207.1716,W,2.21,343.16,061007,,,D*72
-$GPRMC,004250.000,A,3726.9756,N,12207.1772,W,15.37,342.52,061007,,,D*40
-$GPRMC,004255.000,A,3726.9950,N,12207.1942,W,16.40,298.08,061007,,,D*4A
-$GPRMC,004300.000,A,3726.9896,N,12207.2215,W,18.97,241.60,061007,,,D*44
-$GPRMC,004305.000,A,3726.9801,N,12207.2558,W,22.01,268.09,061007,,,D*43
-$GPRMC,004310.000,A,3726.9908,N,12207.2943,W,24.76,304.28,061007,,,D*47
-$GPRMC,004315.000,A,3727.0088,N,12207.3347,W,27.35,295.83,061007,,,D*48
-$GPRMC,004320.000,A,3727.0117,N,12207.3855,W,28.97,271.02,061007,,,D*45
-$GPRMC,004325.000,A,3727.0211,N,12207.4306,W,22.94,303.62,061007,,,D*44
-$GPRMC,004330.000,A,3727.0358,N,12207.4491,W,8.59,313.76,061007,,,D*78
-$GPRMC,004335.000,A,3727.0409,N,12207.4550,W,2.33,313.55,061007,,,D*75
-$GPRMC,004340.000,A,3727.0433,N,12207.4578,W,5.75,314.25,061007,,,D*71
-$GPRMC,004345.000,A,3727.0533,N,12207.4704,W,12.55,314.18,061007,,,D*46
-$GPRMC,004350.000,A,3727.0676,N,12207.4892,W,16.68,312.98,061007,,,D*44
-$GPRMC,004355.000,A,3727.0835,N,12207.5103,W,15.11,313.21,061007,,,D*46
-$GPRMC,004400.000,A,3727.0969,N,12207.5285,W,10.26,312.85,061007,,,D*4A
-$GPRMC,004405.000,A,3727.1006,N,12207.5334,W,0.33,319.16,061007,,,D*71
-$GPRMC,004410.000,A,3727.1007,N,12207.5333,W,0.19,144.98,061007,,,D*77
-$GPRMC,004415.000,A,3727.1005,N,12207.5330,W,0.05,106.63,061007,,,D*7C
-$GPRMC,004420.000,A,3727.1006,N,12207.5327,W,0.05,92.53,061007,,,D*40
-$GPRMC,004425.000,A,3727.1005,N,12207.5323,W,0.17,148.57,061007,,,D*73
-$GPRMC,004430.000,A,3727.1037,N,12207.5355,W,8.70,314.52,061007,,,D*70
-$GPRMC,004435.000,A,3727.1168,N,12207.5516,W,16.83,312.51,061007,,,D*49
-$GPRMC,004440.000,A,3727.1344,N,12207.5787,W,23.06,309.71,061007,,,D*4E
-$GPRMC,004445.000,A,3727.1572,N,12207.6136,W,27.67,308.29,061007,,,D*48
-$GPRMC,004450.000,A,3727.1821,N,12207.6558,W,31.56,306.08,061007,,,D*43
-$GPRMC,004455.000,A,3727.2083,N,12207.7008,W,30.81,306.19,061007,,,D*4F
-$GPRMC,004500.000,A,3727.2324,N,12207.7424,W,27.68,306.75,061007,,,D*41
-$GPRMC,004505.000,A,3727.2519,N,12207.7754,W,16.50,305.19,061007,,,D*48
-$GPRMC,004510.000,A,3727.2570,N,12207.7849,W,0.13,151.16,061007,,,D*7C
-$GPRMC,004515.000,A,3727.2619,N,12207.7927,W,14.27,311.27,061007,,,D*4A
-$GPRMC,004520.000,A,3727.2786,N,12207.8214,W,23.53,303.48,061007,,,D*42
-$GPRMC,004525.000,A,3727.2980,N,12207.8564,W,25.03,306.82,061007,,,D*4F
-$GPRMC,004530.000,A,3727.3199,N,12207.8936,W,27.48,306.29,061007,,,D*4D
-$GPRMC,004535.000,A,3727.3433,N,12207.9339,W,28.66,306.28,061007,,,D*4B
-$GPRMC,004540.000,A,3727.3666,N,12207.9740,W,28.04,306.12,061007,,,D*4C
-$GPRMC,004545.000,A,3727.3886,N,12208.0118,W,25.22,306.50,061007,,,D*4B
-$GPRMC,004550.000,A,3727.4091,N,12208.0461,W,23.34,306.68,061007,,,D*47
-$GPRMC,004555.000,A,3727.4291,N,12208.0747,W,19.76,317.26,061007,,,D*42
-$GPRMC,004600.000,A,3727.4497,N,12208.1015,W,24.00,309.28,061007,,,D*4E
-$GPRMC,004605.000,A,3727.4711,N,12208.1376,W,26.83,305.61,061007,,,D*48
-$GPRMC,004610.000,A,3727.4937,N,12208.1760,W,26.40,305.68,061007,,,D*43
-$GPRMC,004615.000,A,3727.5142,N,12208.2112,W,23.46,306.19,061007,,,D*4B
-$GPRMC,004620.000,A,3727.5326,N,12208.2431,W,21.96,304.30,061007,,,D*4F
-$GPRMC,004625.000,A,3727.5515,N,12208.2693,W,20.21,323.71,061007,,,D*4B
-$GPRMC,004630.000,A,3727.5788,N,12208.2812,W,21.00,352.36,061007,,,D*49
-$GPRMC,004635.000,A,3727.6048,N,12208.2846,W,14.79,351.69,061007,,,D*44
-$GPRMC,004640.000,A,3727.6217,N,12208.2861,W,6.38,359.46,061007,,,D*78
-$GPRMC,004645.000,A,3727.6322,N,12208.2880,W,10.02,331.10,061007,,,D*46
-$GPRMC,004650.000,A,3727.6394,N,12208.3010,W,6.76,277.11,061007,,,D*79
-$GPRMC,004655.000,A,3727.6382,N,12208.3058,W,1.58,256.67,061007,,,D*7E
-$GPRMC,004700.000,A,3727.6253,N,12208.3024,W,6.34,164.31,061007,,,A*70
-$GPRMC,004715.000,A,3727.5854,N,12208.3345,W,5.00,267.98,061007,,,A*79
-$GPRMC,004720.000,A,3727.5993,N,12208.3323,W,6.50,26.91,061007,,,A*4D
-$GPRMC,004725.000,A,3727.6123,N,12208.3159,W,13.14,44.68,061007,,,A*71
diff --git a/location/data/properties b/location/data/properties
deleted file mode 100644
index b6878af..0000000
--- a/location/data/properties
+++ /dev/null
@@ -1,10 +0,0 @@
-requiresNetwork false
-requiresSatellite false
-requiresCell false
-hasMonetaryCost false
-supportsAltitude true
-supportsBearing true
-supportsSpeed true
-repeat true
-accuracy 1
-powerRequirement 1
diff --git a/location/data/test/class b/location/data/test/class
deleted file mode 100644
index 495b172..0000000
--- a/location/data/test/class
+++ /dev/null
@@ -1 +0,0 @@
-android.test.TestLocationProvider
diff --git a/location/data/track/properties b/location/data/track/properties
deleted file mode 100644
index 1f1ed5e..0000000
--- a/location/data/track/properties
+++ /dev/null
@@ -1,10 +0,0 @@
-requiresNetwork true
-requiresSatellite false
-requiresCell false
-hasMonetaryCost false
-supportsAltitude true
-supportsBearing false
-supportsSpeed false
-repeat true
-accuracy 1
-powerRequirement 3
diff --git a/location/data/track/track b/location/data/track/track
deleted file mode 100644
index a69ba2a..0000000
--- a/location/data/track/track
+++ /dev/null
@@ -1 +0,0 @@
-00 003405.000 3725.3433 12205.7921 101.2 65.3
diff --git a/location/java/android/location/IGeocodeProvider.aidl b/location/java/android/location/IGeocodeProvider.aidl
new file mode 100644
index 0000000..e79e8d2
--- /dev/null
+++ b/location/java/android/location/IGeocodeProvider.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.location;
+
+import android.location.Address;
+
+/**
+ * An interface for location providers implementing the Geocoder services.
+ *
+ * {@hide}
+ */
+interface IGeocodeProvider {
+
+    String getFromLocation(double latitude, double longitude, int maxResults,
+        String language, String country, String variant, String appName, out List<Address> addrs);
+
+    String getFromLocationName(String locationName,
+        double lowerLeftLatitude, double lowerLeftLongitude,
+        double upperRightLatitude, double upperRightLongitude, int maxResults,
+        String language, String country, String variant, String appName, out List<Address> addrs);
+}
diff --git a/location/java/android/location/ILocationCollector.aidl b/location/java/android/location/ILocationCollector.aidl
new file mode 100644
index 0000000..b2e1796
--- /dev/null
+++ b/location/java/android/location/ILocationCollector.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.location;
+
+import android.location.Location;
+
+/**
+ * Listens for GPS and cell/wifi changes and anonymously uploads to server 
+ * for improving quality of service of NetworkLocationProvider. 
+ * This service is only enabled when the user has enabled the 
+ * network location provider.
+ *
+ * {@hide}
+ */
+oneway interface ILocationCollector {
+    /**
+     * Updates GPS location if collection is enabled
+     *
+     * @param location location object
+     */
+    void updateLocation(in Location location);
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 69c404a..096622a 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -18,8 +18,11 @@
 
 import android.app.PendingIntent;
 import android.location.Address;
+import android.location.IGeocodeProvider;
 import android.location.IGpsStatusListener;
+import android.location.ILocationCollector;
 import android.location.ILocationListener;
+import android.location.ILocationProvider;
 import android.location.Location;
 import android.os.Bundle;
 
@@ -33,8 +36,6 @@
     List getAllProviders();
     List getProviders(boolean enabledOnly);
 
-    void updateProviders();
-
     void requestLocationUpdates(String provider, long minTime, float minDistance,
         in ILocationListener listener);
     void requestLocationUpdatesPI(String provider, long minTime, float minDistance,
@@ -44,7 +45,10 @@
 
     boolean addGpsStatusListener(IGpsStatusListener listener);
     void removeGpsStatusListener(IGpsStatusListener listener);
-    
+
+    // for reporting callback completion
+    void locationCallbackFinished(ILocationListener listener);
+
     boolean sendExtraCommand(String provider, String command, inout Bundle extras);
 
     void addProximityAlert(double latitude, double longitude, float distance,
@@ -55,6 +59,9 @@
     boolean isProviderEnabled(String provider);
 
     Location getLastKnownLocation(String provider);
+    
+    /* used by location providers to tell the location manager when it has a new location */
+    void setLocation(in Location location);
 
     String getFromLocation(double latitude, double longitude, int maxResults,
         String language, String country, String variant, String appName, out List<Address> addrs);
@@ -73,4 +80,9 @@
     void clearTestProviderEnabled(String provider);
     void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime);
     void clearTestProviderStatus(String provider);
+
+    /* for installing external Location Providers */
+    void setNetworkLocationProvider(ILocationProvider provider);
+    void setLocationCollector(ILocationCollector collector);
+    void setGeocodeProvider(IGeocodeProvider provider);
 }
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
new file mode 100644
index 0000000..82533a5
--- /dev/null
+++ b/location/java/android/location/ILocationProvider.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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.location;
+
+import android.os.Bundle;
+
+/**
+ * An interface for location providers implemented outside of the system process.
+ *
+ * {@hide}
+ */
+interface ILocationProvider {
+
+    /* for LocationProvider */
+    boolean requiresNetwork();
+    boolean requiresSatellite();
+    boolean requiresCell();
+    boolean hasMonetaryCost();
+    boolean supportsAltitude();
+    boolean supportsSpeed();
+    boolean supportsBearing();
+    int getPowerRequirement();
+    int getAccuracy();
+
+    /* for LocationProviderImpl */
+    void enable();
+    void disable();
+    boolean isEnabled();
+    int getStatus(out Bundle extras);
+    long getStatusUpdateTime();
+    void enableLocationTracking(boolean enable);
+    void setMinTime(long minTime);
+    void updateNetworkState(int state);
+    boolean sendExtraCommand(String command, inout Bundle extras);
+    void addListener(int uid);
+    void removeListener(int uid);
+    void wakeLockAcquired();
+    void wakeLockReleased();
+}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 022ee25..dacfeb9 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -26,6 +26,8 @@
 import android.util.Config;
 import android.util.Log;
 
+import com.android.internal.location.DummyLocationProvider;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -101,9 +103,6 @@
      */
     public static final String KEY_LOCATION_CHANGED = "location";
 
-    /** @hide -- does this belong here? */
-    public static final String PROVIDER_DIR = "/data/location";
-
     /** @hide */
     public static final String SYSTEM_DIR = "/data/system/location";
 
@@ -194,6 +193,11 @@
                     mListener.onProviderDisabled((String) msg.obj);
                     break;
             }
+            try {
+                mService.locationCallbackFinished(this);
+            } catch (RemoteException e) {
+                Log.e(TAG, "locationCallbackFinished: RemoteException", e);
+            }
         }
     }
     /**
@@ -313,20 +317,6 @@
     }
 
     /**
-     * Propagates the enabled/disabled state of the providers from the system
-     * settings to the providers themselves.
-     *
-     * {@hide}
-     */
-    public void updateProviders() {
-        try {
-            mService.updateProviders();
-        } catch (RemoteException ex) {
-            Log.e(TAG, "updateProviders: RemoteException", ex);
-        }
-    }
-
-    /**
      * Returns the next looser power requirement, in the sequence:
      *
      * POWER_LOW -> POWER_MEDIUM -> POWER_HIGH -> NO_REQUIREMENT
diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java
index b1670d5..3faba58 100644
--- a/location/java/android/location/LocationProvider.java
+++ b/location/java/android/location/LocationProvider.java
@@ -47,8 +47,10 @@
      * consist only of the characters [a-zA-Z0-9].
      *
      * @throws IllegalArgumentException if name contains an illegal character
+     *
+     * {@hide}
      */
-    LocationProvider(String name) {
+    public LocationProvider(String name) {
         if (name.matches(BAD_CHARS_REGEX)) {
             throw new IllegalArgumentException("name " + name +
                 " contains an illegal character");
diff --git a/location/java/com/android/internal/location/CellState.java b/location/java/com/android/internal/location/CellState.java
deleted file mode 100644
index eb6535e..0000000
--- a/location/java/com/android/internal/location/CellState.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.location;
-
-import android.telephony.CellLocation;
-import android.telephony.TelephonyManager;
-import android.telephony.NeighboringCellInfo;
-import android.telephony.gsm.GsmCellLocation;
-import android.util.Log;
-
-import com.android.internal.telephony.TelephonyProperties;
-
-import java.util.List;
-import java.util.ArrayList;
-
-import android.os.SystemProperties;
-
-/**
- * Stores the cell tower state
- *
- * {@hide}
- */
-public class CellState {
-    
-    public static String TAG = "CellState";
-
-    public static int RADIO_TYPE_GPRS = 1;
-    public static int RADIO_TYPE_CDMA = 2;
-    public static int RADIO_TYPE_WCDMA = 3;
-
-    private int mCid = -1;
-    private int mLac = -1;
-    private int mMcc = -1;
-    private int mMnc = -1;
-    private int mHomeMcc = -1;
-    private int mHomeMnc = -1;
-    private String mCarrier = null;
-    private int mRadioType = -1;
-    private long mTime = 0;
-    private int mSignalStrength = -1;
-
-    private List<NeighborCell> mNeighbors;
-
-    public CellState() {
-        // constructor for invalid cell location
-    }
-
-    public CellState(TelephonyManager telephonyManager, CellLocation location, int signalStrength) {
-        GsmCellLocation loc = (GsmCellLocation)location;
-        mLac = loc.getLac(); // example: 6032
-        mCid = loc.getCid(); // example: 31792
-        mTime = System.currentTimeMillis();
-
-        // Get radio type
-        int radioType = telephonyManager.getNetworkType();
-        if (radioType == TelephonyManager.NETWORK_TYPE_GPRS ||
-            radioType == TelephonyManager.NETWORK_TYPE_EDGE) {
-            mRadioType = RADIO_TYPE_GPRS;
-        } else if (radioType == TelephonyManager.NETWORK_TYPE_UMTS) {
-            mRadioType = RADIO_TYPE_WCDMA;
-        }
-
-        // Get neighboring cells
-        mNeighbors = new ArrayList<NeighborCell>();
-        List<NeighboringCellInfo> neighboringCells = telephonyManager.getNeighboringCellInfo();
-        if (neighboringCells != null) {
-            for (NeighboringCellInfo n : neighboringCells) {
-                if (n.getCid() == NeighboringCellInfo.UNKNOWN_CID) {
-                    continue;
-                }
-
-                if (mRadioType == RADIO_TYPE_WCDMA) {
-                    mNeighbors.add(new NeighborCell(-1, -1, n.getCid(), n.getRssi()));
-                } else if (mRadioType == RADIO_TYPE_GPRS) {
-                    try {
-                        String hexCidLac = Integer.toHexString(n.getCid());
-                        int l = hexCidLac.length();
-                        if (l > 8) {
-                            Log.w(TAG, "Unable to parse 2G Cell \"" + hexCidLac + "\"");
-                            continue;
-                        }
-                        if (l < 8) {
-                            for (int i = 0; i < (8-l); i++) {
-                                hexCidLac = "0" + hexCidLac;
-                            }
-                        }
-                        int lac = Integer.valueOf(hexCidLac.substring(0, 4), 16);
-                        int cid  = Integer.valueOf(hexCidLac.substring(4), 16);
-                        mNeighbors.add(new NeighborCell(cid, lac, -1, n.getRssi()));
-
-                    } catch (Exception e) {
-                        Log.e(TAG, "Error parsing 2G Cell \"" + n.getCid() + "\"", e);
-                    }
-                }
-            }
-        }
-
-        // Get MCC/MNC
-        String operator = telephonyManager.getNetworkOperator();
-        if (operator != null && !operator.equals("")) {
-            // Use a try/catch block to detect index out of bounds or number format exceptions.
-            // If an error occurs, both mMcc and mMnc will be equal to -1.
-            try {
-                String mcc = operator.substring(0, 3);
-                String mnc = operator.substring(3);
-                int mccTmp = Integer.parseInt(mcc);
-                int mncTmp = Integer.parseInt(mnc);
-                
-                // Parsing succeeded, update the instance variables together
-                mMcc = mccTmp;
-                mMnc = mncTmp;
-            } catch (Exception e) {
-                Log.e(TAG, "Error parsing MCC/MNC from operator \"" + operator + "\"", e);
-            }
-        }
-
-        // Get Home MCC/MNC
-        String homeOperator = telephonyManager.getSimOperator();
-        if (homeOperator != null && !homeOperator.equals("")) {
-            // Use a try/catch block to detect index out of bounds or number format exceptions.
-            // If an error occurs, both mHomeMcc and mHomeMnc will be equal to -1.
-            try {
-                String mcc = homeOperator.substring(0, 3);
-                String mnc = homeOperator.substring(3);
-                int mccTmp = Integer.parseInt(mcc);
-                int mncTmp = Integer.parseInt(mnc);
-                
-                // Parsing succeeded, update the instance variables together
-                mHomeMcc = mccTmp;
-                mHomeMnc = mncTmp;
-            } catch (Exception e) {
-                Log.e(TAG, "Error parsing MCC/MNC from home operator \"" + homeOperator + "\"", e);
-            }
-        }
-
-        // Get Carrier
-        String carrier = telephonyManager.getNetworkOperatorName();
-        if (carrier != null && !carrier.equals("")) {
-            mCarrier = carrier;
-        }
-
-        // Initial signal strength
-        mSignalStrength = signalStrength;
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            String neighbors = "[";
-            for (NeighborCell n : mNeighbors) {
-                neighbors += n.toString() + ",";
-            }
-            neighbors += "]";
-            Log.d(TAG, "CellState(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," +
-                mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," +
-                mSignalStrength + "," + neighbors);
-        }
-    }
-
-    public void updateRadioType(int radioType) {
-        mRadioType = radioType;
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.d(TAG, "updateRadioType(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," +
-                mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," +
-                mSignalStrength);
-        }
-    }
-
-    public void updateSignalStrength(int signalStrength) {
-        mSignalStrength = signalStrength;
-
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.d(TAG, "updateSignal(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," + 
-                mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," +
-                mSignalStrength);
-        }
-    }
-
-    public int getCid() {
-        return mCid;
-    }
-
-    public int getLac() {
-        return mLac;
-    }
-
-    public int getMcc() {
-        return mMcc;
-    }
-
-    public int getMnc() {
-        return mMnc;
-    }
-
-    public int getHomeMcc() {
-        return mHomeMcc;
-    }
-
-    public void setHomeMcc(int homeMcc) {
-        this.mHomeMcc = homeMcc;
-    }
-
-    public int getHomeMnc() {
-        return mHomeMnc;
-    }
-
-    public void setHomeMnc(int homeMnc) {
-        this.mHomeMnc = homeMnc;
-    }
-
-    public String getCarrier() {
-        return mCarrier;
-    }
-
-    public void setCarrier(String carrier) {
-        this.mCarrier = carrier;
-    }
-
-    public int getRadioType() {
-        return mRadioType;
-    }
-
-    public long getTime() {
-        return mTime;
-    }
-
-    public int getSignalStrength() {
-        return mSignalStrength;
-    }
-
-    public List<NeighborCell> getNeighbors() {
-        return mNeighbors;
-    }
-
-    public boolean equals(CellState other) {
-        return (mCid == other.mCid && mLac == other.mLac);
-    }
-
-    public boolean isValid() {
-        return (mCid != -1 && mLac != -1);
-    }
-
-    public static class NeighborCell {
-        private int mCid = -1;
-        private int mLac = -1;
-        private int mPsc = -1;
-        private int mRssi = -1;
-
-        NeighborCell(int cid, int lac, int psc, int rssi) {
-            mCid = cid;
-            mLac = lac;
-            mPsc = psc;
-            mRssi = rssi;
-        }
-
-        public int getCid() {
-            return mCid;
-        }
-
-        public int getLac() {
-            return mLac;
-        }
-
-        public int getPsc() {
-            return mPsc;
-        }
-
-        public int getRssi() {
-            return mRssi;
-        }
-
-        public String toString() {
-            if (mPsc != -1) {
-                return String.valueOf(mPsc) + "@" + mRssi;
-            } else {
-                return mCid + ":" + mLac + "@" + mRssi;
-            }
-        }
-    }
-}
diff --git a/location/java/android/location/DummyLocationProvider.java b/location/java/com/android/internal/location/DummyLocationProvider.java
similarity index 95%
rename from location/java/android/location/DummyLocationProvider.java
rename to location/java/com/android/internal/location/DummyLocationProvider.java
index e1cd4e9..ff5e27b 100644
--- a/location/java/android/location/DummyLocationProvider.java
+++ b/location/java/com/android/internal/location/DummyLocationProvider.java
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package android.location;
+package com.android.internal.location;
+
+import android.location.LocationProvider;
 
 /**
  * A stub implementation of LocationProvider used by LocationManager.
@@ -24,7 +26,7 @@
  * 
  * {@hide}
  */
-class DummyLocationProvider extends LocationProvider {
+public class DummyLocationProvider extends LocationProvider {
 
     private static final String TAG = "DummyLocationProvider";
 
@@ -39,7 +41,7 @@
     int mPowerRequirement;
     int mAccuracy;
 
-    /* package */ DummyLocationProvider(String name) {
+    public DummyLocationProvider(String name) {
         super(name);
     }
 
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 887574a..57d3c53 100644
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -22,18 +22,22 @@
 import android.content.IntentFilter;
 import android.location.Criteria;
 import android.location.IGpsStatusListener;
+import android.location.ILocationManager;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
-import android.location.LocationProviderImpl;
+import android.net.ConnectivityManager;
 import android.net.SntpClient;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.util.Config;
 import android.util.Log;
+import android.util.SparseIntArray;
 
+import com.android.internal.app.IBatteryStats;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TelephonyIntents;
 
@@ -97,6 +101,14 @@
     private static final int GPS_STATUS_ENGINE_ON = 3;
     private static final int GPS_STATUS_ENGINE_OFF = 4;
 
+    // these need to match GpsSuplStatusValue defines in gps.h
+    /** SUPL status event values. */
+    private static final int GPS_REQUEST_SUPL_DATA_CONN = 1;
+    private static final int GPS_RELEASE_SUPL_DATA_CONN = 2;
+    private static final int GPS_SUPL_DATA_CONNECTED = 3;
+    private static final int GPS_SUPL_DATA_CONN_DONE = 4;
+    private static final int GPS_SUPL_DATA_CONN_FAILED = 5;
+
     // these need to match GpsLocationFlags enum in gps.h
     private static final int LOCATION_INVALID = 0;
     private static final int LOCATION_HAS_LAT_LONG = 1;
@@ -120,6 +132,11 @@
     private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
     private static final int GPS_DELETE_ALL = 0xFFFF;
 
+    // for mSuplDataConnectionState
+    private static final int SUPL_DATA_CONNECTION_CLOSED = 0;
+    private static final int SUPL_DATA_CONNECTION_OPENING = 1;
+    private static final int SUPL_DATA_CONNECTION_OPEN = 2;
+
     private static final String PROPERTIES_FILE = "/etc/gps.conf";
 
     private int mLocationFlags = LOCATION_INVALID;
@@ -135,8 +152,6 @@
 
     // true if we are enabled
     private boolean mEnabled;
-    // true if we are enabled for location updates
-    private boolean mLocationTracking;
     
     // true if we have network connectivity
     private boolean mNetworkAvailable;
@@ -174,6 +189,12 @@
     private String mSuplHost;
     private int mSuplPort;
     private boolean mSetSuplServer;
+    private String mSuplApn;
+    private int mSuplDataConnectionState;
+    private final ConnectivityManager mConnMgr;
+
+    private final IBatteryStats mBatteryStats;
+    private final SparseIntArray mClientUids = new SparseIntArray();
 
     // how often to request NTP time, in milliseconds
     // current setting 4 hours
@@ -182,8 +203,6 @@
     // current setting - 5 minutes
     private static final long RETRY_INTERVAL = 5*60*1000; 
 
-    private ILocationCollector mCollector;
-
     private class TelephonyBroadcastReceiver extends BroadcastReceiver {
         @Override public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
@@ -196,10 +215,12 @@
                 if (Config.LOGD) {
                     Log.d(TAG, "state: " + state +  " apnName: " + apnName + " reason: " + reason);
                 }
-                if ("CONNECTED".equals(state)) {
-                    native_set_supl_apn(apnName);
-                } else {
-                    native_set_supl_apn("");
+                if ("CONNECTED".equals(state) && apnName != null && apnName.length() > 0) {
+                    mSuplApn = apnName;
+                    if (mSuplDataConnectionState == SUPL_DATA_CONNECTION_OPENING) {
+                        native_supl_data_conn_open(mSuplApn);
+                        mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPEN;
+                    }
                 }
             }
         }
@@ -209,8 +230,8 @@
         return native_is_supported();
     }
 
-    public GpsLocationProvider(Context context) {
-        super(LocationManager.GPS_PROVIDER);
+    public GpsLocationProvider(Context context, ILocationManager locationManager) {
+        super(LocationManager.GPS_PROVIDER, locationManager);
         mContext = context;
 
         TelephonyBroadcastReceiver receiver = new TelephonyBroadcastReceiver();
@@ -218,6 +239,11 @@
         intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
         context.registerReceiver(receiver, intentFilter);
 
+        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        // Battery statistics service to be notified when GPS turns on or off
+        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+
         mProperties = new Properties();
         try {
             File file = new File(PROPERTIES_FILE);
@@ -240,10 +266,6 @@
         }
     }
 
-    public void setLocationCollector(ILocationCollector collector) {
-        mCollector = collector;
-    }
-
     /**
      * Returns true if the provider requires access to a
      * data network (e.g., the Internet), false otherwise.
@@ -355,7 +377,7 @@
 
     /**
      * Enables this provider.  When enabled, calls to getStatus()
-     * and getLocation() must be handled.  Hardware may be started up
+     * must be handled.  Hardware may be started up
      * when the provider is enabled.
      */
     @Override
@@ -385,7 +407,7 @@
 
     /**
      * Disables this provider.  When disabled, calls to getStatus()
-     * and getLocation() need not be handled.  Hardware may be shut
+     * need not be handled.  Hardware may be shut
      * down while the provider is disabled.
      */
     @Override
@@ -412,6 +434,12 @@
             mNetworkThread = null;
         }
 
+        // The GpsEventThread does not wait for the GPS to shutdown
+        // so we need to report the GPS_STATUS_ENGINE_OFF event here
+        if (mNavigating) {
+            reportStatus(GPS_STATUS_ENGINE_OFF);
+        }
+
         native_cleanup();
     }
 
@@ -443,24 +471,8 @@
     }
 
     @Override
-    public boolean getLocation(Location l) {
-        synchronized (mLocation) {
-            // don't report locations without latitude and longitude
-            if ((mLocationFlags & LOCATION_HAS_LAT_LONG) == 0) {
-                return false;
-            }
-            l.set(mLocation);
-            l.setExtras(mLocationExtras);
-            return true;
-        }
-    }
-
-    @Override
     public void enableLocationTracking(boolean enable) {
-        if (mLocationTracking == enable) {
-            return;
-        }
-
+        super.enableLocationTracking(enable);
         if (enable) {
             mFixRequestTime = System.currentTimeMillis();
             mTTFF = 0;
@@ -469,12 +481,6 @@
         } else {
             stopNavigating();
         }
-        mLocationTracking = enable;
-    }
-
-    @Override
-    public boolean isLocationTracking() {
-        return mLocationTracking;
     }
 
     @Override
@@ -552,6 +558,30 @@
     }
 
     @Override
+    public void addListener(int uid) {
+        mClientUids.put(uid, 0);
+        if (mNavigating) {
+            try {
+                mBatteryStats.noteStartGps(uid);
+            } catch (RemoteException e) {
+                Log.w(TAG, "RemoteException in addListener");
+            }
+        }
+    }
+
+    @Override
+    public void removeListener(int uid) {
+        mClientUids.delete(uid);
+        if (mNavigating) {
+            try {
+                mBatteryStats.noteStopGps(uid);
+            } catch (RemoteException e) {
+                Log.w(TAG, "RemoteException in removeListener");
+            }
+        }
+    }
+
+    @Override
     public boolean sendExtraCommand(String command, Bundle extras) {
         
         if ("delete_aiding_data".equals(command)) {
@@ -679,11 +709,7 @@
                 mLocation.removeAccuracy();
             }
 
-            // Send to collector
-            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG
-                    && mCollector != null) {
-                mCollector.updateLocation(mLocation);
-            }
+            reportLocationChanged(mLocation);
         }
 
         if (mStarted && mStatus != AVAILABLE) {
@@ -724,6 +750,20 @@
                 }
             }
 
+            try {
+                // update battery stats
+                for (int i=mClientUids.size() - 1; i >= 0; i--) {
+                    int uid = mClientUids.keyAt(i);
+                    if (mNavigating) {
+                        mBatteryStats.noteStartGps(uid);
+                    } else {
+                        mBatteryStats.noteStopGps(uid);
+                    }
+                }
+            } catch (RemoteException e) {
+                Log.w(TAG, "RemoteException in reportStatus");
+            }
+
             // send an intent to notify that the GPS has been enabled or disabled.
             Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
             intent.putExtra(EXTRA_ENABLED, mNavigating);
@@ -781,7 +821,44 @@
             updateStatus(TEMPORARILY_UNAVAILABLE, mSvCount);
         }
     }
-    
+
+    /**
+     * called from native code to update SUPL status
+     */
+    private void reportSuplStatus(int status) {
+        switch (status) {
+            case GPS_REQUEST_SUPL_DATA_CONN:
+                 int result = mConnMgr.startUsingNetworkFeature(
+                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
+                if (result == Phone.APN_ALREADY_ACTIVE) {
+                    native_supl_data_conn_open(mSuplApn);
+                    mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPEN;
+                } else if (result == Phone.APN_REQUEST_STARTED) {
+                    mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPENING;
+                } else {
+                    native_supl_data_conn_failed();
+                }
+                break;
+            case GPS_RELEASE_SUPL_DATA_CONN:
+                if (mSuplDataConnectionState != SUPL_DATA_CONNECTION_CLOSED) {
+                    mConnMgr.stopUsingNetworkFeature(
+                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
+                    native_supl_data_conn_closed();
+                    mSuplDataConnectionState = SUPL_DATA_CONNECTION_CLOSED;
+                }
+                break;
+            case GPS_SUPL_DATA_CONNECTED:
+                // Log.d(TAG, "GPS_SUPL_DATA_CONNECTED");
+                break;
+            case GPS_SUPL_DATA_CONN_DONE:
+                // Log.d(TAG, "GPS_SUPL_DATA_CONN_DONE");
+                break;
+            case GPS_SUPL_DATA_CONN_FAILED:
+                // Log.d(TAG, "GPS_SUPL_DATA_CONN_FAILED");
+                break;
+        }
+    }
+
     private void xtraDownloadRequest() {
         if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest");
         if (mNetworkThread != null) {
@@ -797,8 +874,8 @@
 
         public void run() {
             if (Config.LOGD) Log.d(TAG, "GpsEventThread starting");
-            // thread exits after disable() is called and navigation has stopped
-            while (mEnabled || mNavigating) {
+            // Exit as soon as disable() is called instead of waiting for the GPS to stop.
+            while (mEnabled) {
                 // this will wait for an event from the GPS,
                 // which will be reported via reportLocation or reportStatus
                 native_wait_for_event();
@@ -1001,6 +1078,8 @@
     private native void native_inject_xtra_data(byte[] data, int length);
 
     // SUPL Support    
+    private native void native_supl_data_conn_open(String apn);
+    private native void native_supl_data_conn_closed();
+    private native void native_supl_data_conn_failed();
     private native void native_set_supl_server(int addr, int port);
-    private native void native_set_supl_apn(String apn);
 }
diff --git a/location/java/com/android/internal/location/GpsXtraDownloader.java b/location/java/com/android/internal/location/GpsXtraDownloader.java
index b8545a6..2a8be57 100644
--- a/location/java/com/android/internal/location/GpsXtraDownloader.java
+++ b/location/java/com/android/internal/location/GpsXtraDownloader.java
@@ -70,11 +70,11 @@
             if (server1 != null) mXtraServers[count++] = server1;
             if (server2 != null) mXtraServers[count++] = server2;
             if (server3 != null) mXtraServers[count++] = server3;
-        }
-        
-        // randomize first server
-        Random random = new Random();
-        mNextServerIndex = random.nextInt(count);
+
+            // randomize first server
+            Random random = new Random();
+            mNextServerIndex = random.nextInt(count);
+        }       
     }
 
     byte[] downloadXtraData() {
diff --git a/location/java/com/android/internal/location/ILocationCollector.java b/location/java/com/android/internal/location/ILocationCollector.java
deleted file mode 100644
index 8a7cdcc..0000000
--- a/location/java/com/android/internal/location/ILocationCollector.java
+++ /dev/null
@@ -1,73 +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.internal.location;
-
-import android.location.Location;
-import android.net.wifi.ScanResult;
-
-import com.android.internal.location.CellState;
-
-import java.util.List;
-
-/**
- * Listens for GPS and cell/wifi changes and anonymously uploads to server for
- * improving quality of service of NetworkLocationProvider. This service is only enabled when
- * the user has enabled the network location provider.
- *
- * {@hide}
- */
-public interface ILocationCollector {
-    /**
-     * Updates GPS location if collection is enabled
-     *
-     * @param location location object
-     */
-    abstract public void updateLocation(Location location);
-
-    /**
-     * Updates wifi scan results if collection is enabled
-     *
-     * @param currentScanResults scan results
-     */
-    abstract public void updateWifiScanResults(List<ScanResult> currentScanResults);
-
-    /**
-     * Updates the status of the network location provider.
-     *
-     * @param enabled true if user has enabled network location based on Google's database
-     * of wifi points and cell towers.
-     */
-    abstract public void updateNetworkProviderStatus(boolean enabled);
-
-    /**
-     * Updates cell tower state. This is usually always up to date so should be uploaded
-     * each time a new location is available.
-     *
-     * @param newState cell state
-     */
-    abstract public void updateCellState(CellState newState);
-
-    /**
-     * Updates the battery health. Battery level is healthy if there is greater than
-     * {@link #MIN_BATTERY_LEVEL} percentage left or if the device is plugged in
-     *
-     * @param scale maximum scale for battery
-     * @param level current level
-     * @param plugged true if device is plugged in
-     */
-    abstract public void updateBatteryState(int scale, int level, boolean plugged);
-}
diff --git a/location/java/com/android/internal/location/INetworkLocationManager.java b/location/java/com/android/internal/location/INetworkLocationManager.java
deleted file mode 100644
index d85ff0a..0000000
--- a/location/java/com/android/internal/location/INetworkLocationManager.java
+++ /dev/null
@@ -1,37 +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.internal.location;
-
-import android.content.Context;
-
-/**
- * Used to register network location and collection services 
- * with the Location Manager Service.
- *
- * {@hide}
- */
-public interface INetworkLocationManager {
-
-    /* callback to allow installation to occur in Location Manager's thread */
-    public interface InstallCallback {
-        void installNetworkLocationProvider(INetworkLocationManager manager);
-    }
-    
-    void setInstallCallback(InstallCallback callback);
-    void setNetworkLocationProvider(INetworkLocationProvider provider);
-    void setLocationCollector(ILocationCollector collector);
-}
\ No newline at end of file
diff --git a/location/java/com/android/internal/location/INetworkLocationProvider.java b/location/java/com/android/internal/location/INetworkLocationProvider.java
deleted file mode 100644
index 730cb48..0000000
--- a/location/java/com/android/internal/location/INetworkLocationProvider.java
+++ /dev/null
@@ -1,95 +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.internal.location;
-
-import android.location.Address;
-import android.location.Location;
-import android.net.wifi.ScanResult;
-
-import com.google.common.io.protocol.ProtoBuf;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Interface for network location provider
- *
- * {@hide}
- */
-public interface INetworkLocationProvider {
-
-    public interface Callback {
-
-        /**
-         * Callback function to notify of a received network location
-         *
-         * @param location location object that is received. may be null if not a valid location
-         * @param successful true if network query was successful, even if no location was found
-         */
-        void locationReceived(Location location, boolean successful);
-    }
-
-    /**
-     * Updates the current cell lock status.
-     *
-     * @param acquired true if a cell lock has been acquired
-     */
-    abstract public void updateCellLockStatus(boolean acquired);
-
-    /**
-     * Notifies the provider if Wifi has been enabled or disabled
-     * by the user
-     *
-     * @param enabled true if wifi is enabled; false otherwise
-     */
-    abstract public void updateWifiEnabledState(boolean enabled);
-
-    /**
-     * Notifies the provider that there are scan results available.
-     *
-     * @param scanResults list of wifi scan results
-     */
-    abstract public void updateWifiScanResults(List<ScanResult> scanResults);
-
-    /**
-     * Adds a list of application clients
-     * Only used by the NetworkLocationProvider
-     *
-     * @param applications list of package names
-     */
-    abstract public void addListener(String[] applications);
-
-    /**
-     * Removes a list of application clients
-     * Only used by the NetworkLocationProvider
-     *
-     * @param applications list of package names
-     */
-    abstract public void removeListener(String[] applications);
-
-
-    abstract public String getFromLocation(double latitude, double longitude, int maxResults,
-        String language, String country, String variant, String appName, List<Address> addrs);
-
-    abstract public String getFromLocationName(String locationName,
-        double lowerLeftLatitude, double lowerLeftLongitude,
-        double upperRightLatitude, double upperRightLongitude, int maxResults,
-        String language, String country, String variant, String appName, List<Address> addrs);
-
-}
diff --git a/location/java/android/location/LocationProviderImpl.java b/location/java/com/android/internal/location/LocationProviderImpl.java
similarity index 71%
rename from location/java/android/location/LocationProviderImpl.java
rename to location/java/com/android/internal/location/LocationProviderImpl.java
index 0962992..fc830f5 100644
--- a/location/java/android/location/LocationProviderImpl.java
+++ b/location/java/com/android/internal/location/LocationProviderImpl.java
@@ -14,21 +14,17 @@
  * limitations under the License.
  */
 
-package android.location;
+package com.android.internal.location;
 
-import com.android.internal.location.CellState;
+import android.location.ILocationManager;
+import android.location.Location;
+import android.location.LocationProvider;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
-
-import android.os.Bundle;
-import android.util.Config;
-import android.util.Log;
 
 /**
  * An abstract superclass for location provider implementations.
@@ -46,11 +42,13 @@
     private static HashMap<String, LocationProviderImpl> sProvidersByName
         = new HashMap<String, LocationProviderImpl>();
 
+    private final ILocationManager mLocationManager;
     private boolean mLocationTracking = false;
     private long mMinTime = 0;
 
-    protected LocationProviderImpl(String name) {
+    protected LocationProviderImpl(String name, ILocationManager locationManager) {
         super(name);
+        mLocationManager = locationManager;
     }
 
     public static void addProvider(LocationProviderImpl provider) {
@@ -63,67 +61,32 @@
         sProvidersByName.remove(provider.getName());
     }
 
-    public static List<LocationProviderImpl> getProviders() {
-        return new ArrayList<LocationProviderImpl>(sProviders);
+    public static ArrayList<LocationProviderImpl> getProviders() {
+        return sProviders;
     }
 
     public static LocationProviderImpl getProvider(String name) {
         return sProvidersByName.get(name);
     }
 
-    public static LocationProviderImpl loadFromClass(File classFile) {
-        if (!classFile.exists()) {
-            return null;
-        }
-        if (Config.LOGD) {
-            Log.d(TAG, "Loading class specifier file " + classFile.getPath());
-        }
-        String className = null;
+    public void reportLocationChanged(Location location) {
         try {
-            BufferedReader br =
-                new BufferedReader(new FileReader(classFile), 8192);
-            className = br.readLine();
-            br.close();
-            Class providerClass = Class.forName(className);
-            if (Config.LOGD) {
-                Log.d(TAG, "Loading provider class " + providerClass.getName());
-            }
-            LocationProviderImpl provider =
-                (LocationProviderImpl) providerClass.newInstance();
-            if (Config.LOGD) {
-                Log.d(TAG, "Got provider instance " + provider);
-            }
-
-            return provider;
-        } catch (IOException ioe) {
-            Log.e(TAG, "IOException loading config file " +
-                  classFile.getPath(), ioe);
-        } catch (IllegalAccessException iae) {
-            Log.e(TAG, "IllegalAccessException loading class " +
-                  className, iae);
-        } catch (InstantiationException ie) {
-            Log.e(TAG, "InstantiationException loading class " +
-                  className, ie);
-        } catch (ClassNotFoundException cnfe) {
-            Log.e(TAG, "ClassNotFoundException loading class " +
-                  className, cnfe);
-        } catch (ClassCastException cce) {
-            Log.e(TAG, "ClassCastException loading class " +
-                  className, cce);
+            mLocationManager.setLocation(location);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException calling ILocationManager.setLocation");
         }
-        return null;
     }
-
+    
     /**
      * Enables this provider.  When enabled, calls to {@link #getStatus()}
-     * and {@link #getLocation} must be handled.  Hardware may be started up
+     * must be handled.  Hardware may be started up
      * when the provider is enabled.
      */
     public abstract void enable();
 
     /**
      * Disables this provider.  When disabled, calls to {@link #getStatus()}
-     * and {@link #getLocation} need not be handled.  Hardware may be shut
+     * need not be handled.  Hardware may be shut
      * down while the provider is disabled.
      */
     public abstract void disable();
@@ -175,15 +138,6 @@
     }
 
     /**
-     * Sets a Location object with the information gathered
-     * during the most recent fix.
-     *
-     * @param l location object to set
-     * @return true if a location fix is available
-     */
-    public abstract boolean getLocation(Location l);
-
-    /**
      * Notifies the location provider that clients are listening for locations.
      * Called with enable set to true when the first client is added and
      * called with enable set to false when the last client is removed.
@@ -238,15 +192,6 @@
     }
 
     /**
-     * Updates the cell state for the given provider. This function must be
-     * overwritten if {@link #requiresCell} returns true.
-     *
-     * @param state cell state
-     */
-    public void updateCellState(CellState state) {
-    }
-
-    /**
      * Implements addditional location provider specific additional commands.
      *
      * @param command name of the command to send to the provider.
@@ -258,4 +203,32 @@
     public boolean sendExtraCommand(String command, Bundle extras) {
         return false;
     }
+
+    /**
+     * Informs the location provider when a new client is listening for location information
+     *
+     * @param uid the uid of the client proces
+     */
+    public void addListener(int uid) {
+    }
+
+    /**
+     * Informs the location provider when a client is no longer listening for location information
+     *
+     * @param uid the uid of the client proces
+     */
+    public void removeListener(int uid) {
+    }
+
+    /**
+     * Informs the location provider when the location manager service has acquired its wake lock
+     */
+    public void wakeLockAcquired() {
+    }
+
+    /**
+     * Informs the location provider when the location manager service has released its wake lock
+     */
+    public void wakeLockReleased() {
+    }
 }
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
new file mode 100644
index 0000000..d3c86db
--- /dev/null
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -0,0 +1,255 @@
+/*
+ * 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.location;
+
+import android.location.Address;
+import android.location.ILocationManager;
+import android.location.ILocationProvider;
+import android.location.Location;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * A class for proxying remote ILocationProvider implementations.
+ *
+ * {@hide}
+ */
+public class LocationProviderProxy extends LocationProviderImpl {
+
+    private static final String TAG = "LocationProviderProxy";
+
+    private final ILocationProvider mProvider;
+
+    public LocationProviderProxy(String name, ILocationManager locationManager,
+            ILocationProvider provider) {
+        super(name, locationManager);
+        mProvider = provider;
+    }
+
+    @Override
+    public boolean requiresNetwork() {
+        try {
+            return mProvider.requiresNetwork();
+        } catch (RemoteException e) {
+            Log.e(TAG, "requiresNetwork failed", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean requiresSatellite() {
+        try {
+            return mProvider.requiresSatellite();
+        } catch (RemoteException e) {
+            Log.e(TAG, "requiresSatellite failed", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean requiresCell() {
+        try {
+            return mProvider.requiresCell();
+        } catch (RemoteException e) {
+            Log.e(TAG, "requiresCell failed", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean hasMonetaryCost() {
+        try {
+            return mProvider.hasMonetaryCost();
+        } catch (RemoteException e) {
+            Log.e(TAG, "hasMonetaryCost failed", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean supportsAltitude() {
+        try {
+            return mProvider.supportsAltitude();
+        } catch (RemoteException e) {
+            Log.e(TAG, "supportsAltitude failed", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean supportsSpeed() {
+        try {
+            return mProvider.supportsSpeed();
+        } catch (RemoteException e) {
+            Log.e(TAG, "supportsSpeed failed", e);
+            return false;
+        }
+    }
+
+     @Override
+    public boolean supportsBearing() {
+        try {
+            return mProvider.supportsBearing();
+        } catch (RemoteException e) {
+            Log.e(TAG, "supportsBearing failed", e);
+            return false;
+        }
+    }
+
+    @Override
+    public int getPowerRequirement() {
+        try {
+            return mProvider.getPowerRequirement();
+        } catch (RemoteException e) {
+            Log.e(TAG, "getPowerRequirement failed", e);
+            return 0;
+        }
+    }
+
+    @Override
+    public int getAccuracy() {
+        try {
+            return mProvider.getAccuracy();
+        } catch (RemoteException e) {
+            Log.e(TAG, "getAccuracy failed", e);
+            return 0;
+        }
+    }
+
+    @Override
+    public void enable() {
+        try {
+            mProvider.enable();
+        } catch (RemoteException e) {
+            Log.e(TAG, "enable failed", e);
+        }
+    }
+
+    @Override
+    public void disable() {
+        try {
+            mProvider.disable();
+        } catch (RemoteException e) {
+            Log.e(TAG, "disable failed", e);
+        }
+    }
+
+    @Override
+    public boolean isEnabled() {
+        try {
+            return mProvider.isEnabled();
+        } catch (RemoteException e) {
+            Log.e(TAG, "isEnabled failed", e);
+            return false;
+        }
+    }
+
+    @Override
+    public int getStatus(Bundle extras) {
+        try {
+            return mProvider.getStatus(extras);
+        } catch (RemoteException e) {
+            Log.e(TAG, "getStatus failed", e);
+            return 0;
+        }
+    }
+
+    @Override
+    public long getStatusUpdateTime() {
+        try {
+            return mProvider.getStatusUpdateTime();
+        } catch (RemoteException e) {
+            Log.e(TAG, "getStatusUpdateTime failed", e);
+            return 0;
+        }
+    }
+
+    @Override
+    public void enableLocationTracking(boolean enable) {
+        try {
+            super.enableLocationTracking(enable);
+            mProvider.enableLocationTracking(enable);
+        } catch (RemoteException e) {
+            Log.e(TAG, "enableLocationTracking failed", e);
+        }
+    }
+
+    @Override
+    public void setMinTime(long minTime) {
+        try {
+            super.setMinTime(minTime);
+            mProvider.setMinTime(minTime);
+        } catch (RemoteException e) {
+            Log.e(TAG, "setMinTime failed", e);
+        }
+    }
+
+    @Override
+    public void updateNetworkState(int state) {
+        try {
+            mProvider.updateNetworkState(state);
+        } catch (RemoteException e) {
+            Log.e(TAG, "updateNetworkState failed", e);
+        }
+    }
+
+    @Override
+    public boolean sendExtraCommand(String command, Bundle extras) {
+        try {
+            return mProvider.sendExtraCommand(command, extras);
+        } catch (RemoteException e) {
+            Log.e(TAG, "sendExtraCommand failed", e);
+            return false;
+        }
+    }
+
+    public void addListener(int uid) {
+        try {
+            mProvider.addListener(uid);
+        } catch (RemoteException e) {
+            Log.e(TAG, "addListener failed", e);
+        }
+    }
+
+    public void removeListener(int uid) {
+        try {
+            mProvider.removeListener(uid);
+        } catch (RemoteException e) {
+            Log.e(TAG, "removeListener failed", e);
+        }
+    }
+
+    public void wakeLockAcquired() {
+        try {
+            mProvider.wakeLockAcquired();
+        } catch (RemoteException e) {
+            Log.e(TAG, "wakeLockAcquired failed", e);
+        }
+    }
+
+    public void wakeLockReleased() {
+        try {
+            mProvider.wakeLockReleased();
+        } catch (RemoteException e) {
+            Log.e(TAG, "wakeLockReleased failed", e);
+        }
+    }
+}
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
new file mode 100644
index 0000000..6336e2b
--- /dev/null
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -0,0 +1,178 @@
+/*
+ * 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.location;
+
+import android.location.ILocationManager;
+import android.location.Location;
+import android.os.Bundle;
+import android.util.PrintWriterPrinter;
+
+import java.io.PrintWriter;
+
+/**
+ * A mock location provider used by LocationManagerService to implement test providers.
+ *
+ * {@hide}
+ */
+public class MockProvider extends LocationProviderImpl {
+    private final boolean mRequiresNetwork;
+    private final boolean mRequiresSatellite;
+    private final boolean mRequiresCell;
+    private final boolean mHasMonetaryCost;
+    private final boolean mSupportsAltitude;
+    private final boolean mSupportsSpeed;
+    private final boolean mSupportsBearing;
+    private final int mPowerRequirement;
+    private final int mAccuracy;
+    private final Location mLocation;
+    private int mStatus;
+    private long mStatusUpdateTime;
+    private final Bundle mExtras = new Bundle();
+    private boolean mHasLocation;
+    private boolean mHasStatus;
+    private boolean mEnabled;
+
+    public MockProvider(String name,  ILocationManager locationManager,
+        boolean requiresNetwork, boolean requiresSatellite,
+        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
+        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
+        super(name, locationManager);
+
+        mRequiresNetwork = requiresNetwork;
+        mRequiresSatellite = requiresSatellite;
+        mRequiresCell = requiresCell;
+        mHasMonetaryCost = hasMonetaryCost;
+        mSupportsAltitude = supportsAltitude;
+        mSupportsBearing = supportsBearing;
+        mSupportsSpeed = supportsSpeed;
+        mPowerRequirement = powerRequirement;
+        mAccuracy = accuracy;
+        mLocation = new Location(name);
+    }
+
+    @Override
+    public void disable() {
+        mEnabled = false;
+    }
+
+    @Override
+    public void enable() {
+        mEnabled = true;
+    }
+
+    @Override
+    public int getStatus(Bundle extras) {
+        if (mHasStatus) {
+            extras.clear();
+            extras.putAll(mExtras);
+            return mStatus;
+        } else {
+            return AVAILABLE;
+        }
+    }
+
+    @Override
+    public long getStatusUpdateTime() {
+        return mStatusUpdateTime;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    @Override
+    public int getAccuracy() {
+        return mAccuracy;
+    }
+
+    @Override
+    public int getPowerRequirement() {
+        return mPowerRequirement;
+    }
+
+    @Override
+    public boolean hasMonetaryCost() {
+        return mHasMonetaryCost;
+    }
+
+    @Override
+    public boolean requiresCell() {
+        return mRequiresCell;
+    }
+
+    @Override
+    public boolean requiresNetwork() {
+        return mRequiresNetwork;
+    }
+
+    @Override
+    public boolean requiresSatellite() {
+        return mRequiresSatellite;
+    }
+
+    @Override
+    public boolean supportsAltitude() {
+        return mSupportsAltitude;
+    }
+
+    @Override
+    public boolean supportsBearing() {
+        return mSupportsBearing;
+    }
+
+    @Override
+    public boolean supportsSpeed() {
+        return mSupportsSpeed;
+    }
+
+    public void setLocation(Location l) {
+        mLocation.set(l);
+        mHasLocation = true;
+        reportLocationChanged(mLocation);
+    }
+
+    public void clearLocation() {
+        mHasLocation = false;
+    }
+
+    public void setStatus(int status, Bundle extras, long updateTime) {
+        mStatus = status;
+        mStatusUpdateTime = updateTime;
+        mExtras.clear();
+        if (extras != null) {
+            mExtras.putAll(extras);
+        }
+        mHasStatus = true;
+    }
+
+    public void clearStatus() {
+        mHasStatus = false;
+        mStatusUpdateTime = 0;
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + getName());
+        pw.println(prefix + "mHasLocation=" + mHasLocation);
+        pw.println(prefix + "mLocation:");
+        mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
+        pw.println(prefix + "mHasStatus=" + mHasStatus);
+        pw.println(prefix + "mStatus=" + mStatus);
+        pw.println(prefix + "mStatusUpdateTime=" + mStatusUpdateTime);
+        pw.println(prefix + "mExtras=" + mExtras);
+    }
+}
diff --git a/location/java/com/android/internal/location/TrackProvider.java b/location/java/com/android/internal/location/TrackProvider.java
deleted file mode 100644
index 545d7dc..0000000
--- a/location/java/com/android/internal/location/TrackProvider.java
+++ /dev/null
@@ -1,720 +0,0 @@
-// Copyright 2007 The Android Open Source Project
-
-package com.android.internal.location;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-import android.location.Criteria;
-import android.location.Location;
-import android.location.LocationProviderImpl;
-import android.os.Bundle;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * A dummy provider that returns positions interpolated from a sequence
- * of caller-supplied waypoints.  The waypoints are supplied as a
- * String containing one or more numeric quadruples of the form:
- * <br>
- * <code>
- * <time in millis> <latitude> <longitude> <altitude>
- * </code>
- *
- * <p> The waypoints must be supplied in increasing timestamp order.
- *
- * <p> The time at which the provider is constructed is considered to
- * be time 0, and further requests for positions will return a
- * position that is linearly interpolated between the waypoints whose
- * timestamps are closest to the amount of wall clock time that has
- * elapsed since time 0.
- *
- * <p> Following the time of the last waypoint, the position of that
- * waypoint will continue to be returned indefinitely.
- *
- * {@hide}
- */
-public class TrackProvider extends LocationProviderImpl {
-    static final String LOG_TAG = "TrackProvider";
-
-    private static final long INTERVAL = 1000L;
-
-    private boolean mEnabled = true;
-
-    private double mLatitude;
-    private double mLongitude;
-    private boolean mHasAltitude;
-    private boolean mHasBearing;
-    private boolean mHasSpeed;
-    private double mAltitude;
-    private float mBearing;
-    private float mSpeed;
-    private Bundle mExtras;
-
-    private long mBaseTime;
-    private long mLastTime = -1L;
-    private long mTime;
-
-    private long mMinTime;
-    private long mMaxTime;
-
-    private List<Waypoint> mWaypoints = new ArrayList<Waypoint>();
-    private int mWaypointIndex = 0;
-
-    private boolean mRequiresNetwork = false;
-    private boolean mRequiresSatellite = false;
-    private boolean mRequiresCell = false;
-    private boolean mHasMonetaryCost = false;
-    private boolean mSupportsAltitude = true;
-    private boolean mSupportsSpeed = true;
-    private boolean mSupportsBearing = true;
-    private boolean mRepeat = false;
-    private int mPowerRequirement = Criteria.POWER_LOW;
-    private int mAccuracy = Criteria.ACCURACY_COARSE;
-
-    private float mTrackSpeed = 100.0f; // km/hr - default for kml tracks
-
-    private Location mInitialLocation;
-
-    private void close(Reader rdr) {
-        try {
-            if (rdr != null) {
-                rdr.close();
-            }
-        } catch (IOException e) {
-            Log.w(LOG_TAG, "Exception closing reader", e);
-        }
-    }
-
-    public void readTrack(File trackFile) {
-        BufferedReader br = null;
-        try {
-            br = new BufferedReader(new FileReader(trackFile), 8192);
-            String s;
-
-            long lastTime = -Long.MAX_VALUE;
-            while ((s = br.readLine()) != null) {
-                String[] tokens = s.split("\\s+");
-                if (tokens.length != 4 && tokens.length != 6) {
-                    Log.e(LOG_TAG, "Got track \"" + s +
-                        "\", wanted <time> <long> <lat> <alt> [<bearing> <speed>]");
-                    continue;
-                }
-                long time;
-                double longitude, latitude, altitude;
-                try {
-                    time = Long.parseLong(tokens[0]);
-                    longitude = Double.parseDouble(tokens[1]);
-                    latitude = Double.parseDouble(tokens[2]);
-                    altitude = Double.parseDouble(tokens[3]);
-                } catch (NumberFormatException e) {
-                    Log.e(LOG_TAG, "Got track \"" + s +
-                        "\", wanted <time> <long> <lat> <alt> " +
-                        "[<bearing> <speed>]", e);
-                    continue;
-                }
-
-                Waypoint w = new Waypoint(getName(), time, latitude, longitude, altitude);
-                if (tokens.length >= 6) {
-                    float bearing, speed;
-                    try {
-                        bearing = Float.parseFloat(tokens[4]);
-                        speed = Float.parseFloat(tokens[5]);
-                        w.setBearing(bearing);
-                        w.setSpeed(speed);
-                    } catch (NumberFormatException e) {
-                        Log.e(LOG_TAG, "Ignoring bearing and speed \"" +
-                            tokens[4] + "\", \"" + tokens[5] + "\"", e);
-                    }
-                }
-
-                if (mInitialLocation == null) {
-                    mInitialLocation = w.getLocation();
-                }
-
-                // Ignore waypoints whose time is less than or equal to 0 or
-                // the time of the previous waypoint
-                if (time < 0) {
-                    Log.e(LOG_TAG, "Ignoring waypoint at negative time=" + time);
-                    continue;
-                }
-                if (time <= lastTime) {
-                    Log.e(LOG_TAG, "Ignoring waypoint at time=" + time +
-                        " (< " + lastTime + ")");
-                    continue;
-                }
-
-                mWaypoints.add(w);
-                lastTime = time;
-            }
-
-            setTimes();
-            return;
-        } catch (IOException e) {
-            Log.e(LOG_TAG, "Exception reading track file", e);
-            mWaypoints.clear();
-        } finally {
-            close(br);
-        }
-    }
-
-    public void readKml(File kmlFile) {
-        FileReader kmlReader = null;
-        try {
-            kmlReader = new FileReader(kmlFile);
-            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
-            XmlPullParser xpp = factory.newPullParser();
-            xpp.setInput(kmlReader);
-
-            // Concatenate the text of each <coordinates> tag
-            boolean inCoordinates = false;
-            StringBuilder sb = new StringBuilder();
-            int eventType = xpp.getEventType();
-            do {
-                if (eventType == XmlPullParser.START_DOCUMENT) {
-                    // do nothing
-                } else if (eventType == XmlPullParser.END_DOCUMENT) {
-                    // do nothing
-                } else if (eventType == XmlPullParser.START_TAG) {
-                    String startTagName = xpp.getName();
-                    if (startTagName.equals("coordinates")) {
-                        inCoordinates = true;
-                    }
-                } else if (eventType == XmlPullParser.END_TAG) {
-                    String endTagName = xpp.getName();
-                    if (endTagName.equals("coordinates")) {
-                        inCoordinates = false;
-                    }
-                } else if (eventType == XmlPullParser.TEXT) {
-                    if (inCoordinates) {
-                        sb.append(xpp.getText());
-                        sb.append(' ');
-                    }
-                }
-                eventType = xpp.next();
-            } while (eventType != XmlPullParser.END_DOCUMENT);
-
-            String coordinates = sb.toString();
-
-            // Parse the "lon,lat,alt" triples and supply times
-            // for each waypoint based on a constant speed
-            Location loc = null;
-            double KM_PER_HOUR = mTrackSpeed;
-            double KM_PER_METER = 1.0 / 1000.0;
-            double MILLIS_PER_HOUR = 60.0 * 60.0 * 1000.0;
-            double MILLIS_PER_METER =
-                (1.0 / KM_PER_HOUR) * (KM_PER_METER) * (MILLIS_PER_HOUR);
-            long time = 0L;
-
-            StringTokenizer st = new StringTokenizer(coordinates, ", ");
-            while (st.hasMoreTokens()) {
-                try {
-                    String lon = st.nextToken();
-                    String lat = st.nextToken();
-                    String alt = st.nextToken();
-                    if (Config.LOGD) {
-                        Log.d(LOG_TAG,
-                            "lon=" + lon + ", lat=" + lat + ", alt=" + alt);
-                    }
-
-                    double nLongitude = Double.parseDouble(lon);
-                    double nLatitude = Double.parseDouble(lat);
-                    double nAltitude = Double.parseDouble(alt);
-
-                    Location nLoc = new Location(getName());
-                    nLoc.setLatitude(nLatitude);
-                    nLoc.setLongitude(nLongitude);
-                    if (loc != null) {
-                        double distance = loc.distanceTo(nLoc);
-                        if (Config.LOGD) {
-                            Log.d(LOG_TAG, "distance = " + distance);
-                        }
-                        time += (long) (distance * MILLIS_PER_METER);
-                    }
-
-                    Waypoint w = new Waypoint(getName(), time,
-                        nLatitude, nLongitude, nAltitude);
-                    if (supportsSpeed()) {
-                        w.setSpeed(mTrackSpeed);
-                    }
-                    if (supportsBearing()) {
-                        w.setBearing(0.0f);
-                    }
-                    mWaypoints.add(w);
-
-                    if (mInitialLocation == null) {
-                        mInitialLocation = w.getLocation();
-                    }
-
-                    loc = nLoc;
-                } catch (NumberFormatException nfe) {
-                    Log.e(LOG_TAG, "Got NumberFormatException reading KML data: " +
-                        nfe, nfe);
-                }
-            }
-
-            setTimes();
-            return;
-        } catch (IOException ioe) {
-            mWaypoints.clear();
-            Log.e(LOG_TAG, "Exception reading KML data: " + ioe, ioe);
-            // fall through
-        } catch (XmlPullParserException xppe) {
-            mWaypoints.clear();
-            Log.e(LOG_TAG, "Exception reading KML data: " + xppe, xppe);
-            // fall through
-        } finally {
-            close(kmlReader);
-        }
-    }
-
-    public void readNmea(String name, File file) {
-        BufferedReader br = null;
-        try {
-            br = new BufferedReader(new FileReader(file), 8192);
-            String s;
-
-            String provider = getName();
-            NmeaParser parser = new NmeaParser(name);
-            while ((s = br.readLine()) != null) {
-                boolean newWaypoint = parser.parseSentence(s);
-                if (newWaypoint) {
-                    Location loc = parser.getLocation();
-                    Waypoint w = new Waypoint(loc);
-                    mWaypoints.add(w);
-                    // Log.i(TAG, "Got waypoint " + w);
-                }
-            }
-
-            setTimes();
-            return;
-        } catch (IOException ioe) {
-            Log.e(LOG_TAG, "Exception reading NMEA data: " + ioe);
-            mWaypoints.clear();
-        } finally {
-            close(br);
-        }
-    }
-
-    private static boolean booleanVal(String tf) {
-        return (tf == null) || (tf.equalsIgnoreCase("true"));
-    }
-
-    private static int intVal(String val) {
-        try {
-            return (val == null) ? 0 : Integer.parseInt(val);
-        } catch (NumberFormatException nfe) {
-            return 0;
-        }
-    }
-
-    private static float floatVal(String val) {
-        try {
-            return (val == null) ? 0 : Float.parseFloat(val);
-        } catch (NumberFormatException nfe) {
-            return 0.0f;
-        }
-    }
-
-    public void readProperties(File propertiesFile) {
-        BufferedReader br = null;
-        if (!propertiesFile.exists()) {
-            return;
-        }
-        try {
-            if (Config.LOGD) {
-                Log.d(LOG_TAG, "Loading properties file " +
-                    propertiesFile.getPath());
-            }
-            br = new BufferedReader(new FileReader(propertiesFile), 8192);
-
-            String s;
-            while ((s = br.readLine()) != null) {
-                StringTokenizer st = new StringTokenizer(s);
-                String command = null;
-                String value = null;
-                if (!st.hasMoreTokens()) {
-                    continue;
-                }
-                command = st.nextToken();
-                if (st.hasMoreTokens()) {
-                    value = st.nextToken();
-                }
-
-                if (command.equalsIgnoreCase("requiresNetwork")) {
-                    setRequiresNetwork(booleanVal(value));
-                } else if (command.equalsIgnoreCase("requiresSatellite")) {
-                    setRequiresSatellite(booleanVal(value));
-                } else if (command.equalsIgnoreCase("requiresCell")) {
-                    setRequiresCell(booleanVal(value));
-                } else if (command.equalsIgnoreCase("hasMonetaryCost")) {
-                    setHasMonetaryCost(booleanVal(value));
-                } else if (command.equalsIgnoreCase("supportsAltitude")) {
-                    setSupportsAltitude(booleanVal(value));
-                } else if (command.equalsIgnoreCase("supportsBearing")) {
-                    setSupportsBearing(booleanVal(value));
-                } else if (command.equalsIgnoreCase("repeat")) {
-                    setRepeat(booleanVal(value));
-                } else if (command.equalsIgnoreCase("supportsSpeed")) {
-                    setSupportsSpeed(booleanVal(value));
-                } else if (command.equalsIgnoreCase("powerRequirement")) {
-                    setPowerRequirement(intVal(value));
-                } else if (command.equalsIgnoreCase("accuracy")) {
-                    setAccuracy(intVal(value));
-                } else if (command.equalsIgnoreCase("trackspeed")) {
-                    setTrackSpeed(floatVal(value));
-                } else {
-                    Log.e(LOG_TAG, "Unknown command \"" + command + "\"");
-                }
-            }
-        } catch (IOException ioe) {
-            Log.e(LOG_TAG, "IOException reading properties file " +
-                propertiesFile.getPath(), ioe);
-        } finally {
-            try {
-                if (br != null) {
-                    br.close();
-                }
-            } catch (IOException e) {
-                Log.w(LOG_TAG, "IOException closing properties file " +
-                    propertiesFile.getPath(), e);
-            }
-        }
-    }
-
-    public TrackProvider(String name) {
-        super(name);
-        setTimes();
-    }
-
-    public TrackProvider(String name, File file) {
-        this(name);
-
-        String filename = file.getName();
-        if (filename.endsWith("kml")) {
-            readKml(file);
-        } else if (filename.endsWith("nmea")) {
-            readNmea(getName(), file);
-        } else if (filename.endsWith("track")) {
-            readTrack(file);
-        } else {
-            Log.e(LOG_TAG, "Can't initialize TrackProvider from file " +
-                filename + " (not *kml, *nmea, or *track)");
-        }
-        setTimes();
-    }
-
-    private void setTimes() {
-        mBaseTime = System.currentTimeMillis();
-        if (mWaypoints.size() >= 2) {
-            mMinTime = mWaypoints.get(0).getTime();
-            mMaxTime = mWaypoints.get(mWaypoints.size() - 1).getTime();
-        } else {
-            mMinTime = mMaxTime = 0;
-        }
-    }
-
-    private double interp(double d0, double d1, float frac) {
-        return d0 + frac * (d1 - d0);
-    }
-
-    private void update() {
-        // Don't update the position at all unless INTERVAL milliseconds
-        // have passed since the last request
-        long time = System.currentTimeMillis() - mBaseTime;
-        if (time - mLastTime < INTERVAL) {
-            return;
-        }
-
-        List<Waypoint> waypoints = mWaypoints;
-        if (waypoints == null) {
-            return;
-        }
-        int size = waypoints.size();
-        if (size < 2) {
-            return;
-        }
-
-        long t = time;
-        if (t < mMinTime) {
-            t = mMinTime;
-        }
-        if (mRepeat) {
-            t -= mMinTime;
-            long deltaT = mMaxTime - mMinTime;
-            t %= 2 * deltaT;
-            if (t > deltaT) {
-                t = 2 * deltaT - t;
-            }
-            t += mMinTime;
-        } else if (t > mMaxTime) {
-            t = mMaxTime;
-        }
-
-        // Locate the time interval for the current time
-        // We slide the window since we don't expect to move
-        // much between calls
-
-        Waypoint w0 = waypoints.get(mWaypointIndex);
-        Waypoint w1 = waypoints.get(mWaypointIndex + 1);
-
-        // If the right end of the current interval is too early,
-        // move forward to the next waypoint
-        while (t > w1.getTime()) {
-            w0 = w1;
-            w1 = waypoints.get(++mWaypointIndex + 1);
-        }
-        // If the left end of the current interval is too late,
-        // move back to the previous waypoint
-        while (t < w0.getTime()) {
-            w1 = w0;
-            w0 = waypoints.get(--mWaypointIndex);
-        }
-
-        // Now we know that w0.mTime <= t <= w1.mTime
-        long w0Time = w0.getTime();
-        long w1Time = w1.getTime();
-        long dt = w1Time - w0Time;
-
-        float frac = (dt == 0) ? 0 : ((float) (t - w0Time) / dt);
-        mLatitude  = interp(w0.getLatitude(), w1.getLatitude(), frac);
-        mLongitude = interp(w0.getLongitude(), w1.getLongitude(), frac);
-        mHasAltitude = w0.hasAltitude() && w1.hasAltitude();
-        if (mSupportsAltitude && mHasAltitude) {
-            mAltitude  = interp(w0.getAltitude(), w1.getAltitude(), frac);
-        }
-        if (mSupportsBearing) {
-            mHasBearing = frac <= 0.5f ? w0.hasBearing() : w1.hasBearing();
-            if (mHasBearing) {
-                mBearing  = frac <= 0.5f ? w0.getBearing() : w1.getBearing();
-            }
-        }
-        if (mSupportsSpeed) {
-            mHasSpeed = frac <= 0.5f ? w0.hasSpeed() : w1.hasSpeed();
-            if (mHasSpeed) {
-                mSpeed  = frac <= 0.5f ? w0.getSpeed() : w1.getSpeed();
-            }
-        }
-        mLastTime = time;
-        mTime = time;
-    }
-
-    public void setRequiresNetwork(boolean requiresNetwork) {
-        mRequiresNetwork = requiresNetwork;
-    }
-
-    @Override public boolean requiresNetwork() {
-        return mRequiresNetwork;
-    }
-
-    public void setRequiresSatellite(boolean requiresSatellite) {
-        mRequiresSatellite = requiresSatellite;
-    }
-
-    @Override public boolean requiresSatellite() {
-        return mRequiresSatellite;
-    }
-
-    public void setRequiresCell(boolean requiresCell) {
-        mRequiresCell = requiresCell;
-    }
-
-    @Override public boolean requiresCell() {
-        return mRequiresCell;
-    }
-
-    public void setHasMonetaryCost(boolean hasMonetaryCost) {
-        mHasMonetaryCost = hasMonetaryCost;
-    }
-
-    @Override public boolean hasMonetaryCost() {
-        return mHasMonetaryCost;
-    }
-
-    public void setSupportsAltitude(boolean supportsAltitude) {
-        mSupportsAltitude = supportsAltitude;
-    }
-
-    @Override public boolean supportsAltitude() {
-        return mSupportsAltitude;
-    }
-
-    public void setSupportsSpeed(boolean supportsSpeed) {
-        mSupportsSpeed = supportsSpeed;
-    }
-
-    @Override public boolean supportsSpeed() {
-        return mSupportsSpeed;
-    }
-
-    public void setSupportsBearing(boolean supportsBearing) {
-        mSupportsBearing = supportsBearing;
-    }
-
-    @Override public boolean supportsBearing() {
-        return mSupportsBearing;
-    }
-
-    public void setRepeat(boolean repeat) {
-        mRepeat = repeat;
-    }
-
-    public void setPowerRequirement(int powerRequirement) {
-        if (powerRequirement < Criteria.POWER_LOW ||
-            powerRequirement > Criteria.POWER_HIGH) {
-            throw new IllegalArgumentException("powerRequirement = " +
-                powerRequirement);
-        }
-        mPowerRequirement = powerRequirement;
-    }
-
-    @Override public int getPowerRequirement() {
-        return mPowerRequirement;
-    }
-
-    public void setAccuracy(int accuracy) {
-        mAccuracy = accuracy;
-    }
-
-    @Override public int getAccuracy() {
-        return mAccuracy;
-    }
-
-    public void setTrackSpeed(float trackSpeed) {
-        mTrackSpeed = trackSpeed;
-    }
-
-    @Override public void enable() {
-        mEnabled = true;
-    }
-
-    @Override public void disable() {
-        mEnabled = false;
-    }
-
-    @Override public boolean isEnabled() {
-        return mEnabled;
-    }
-
-    @Override public int getStatus(Bundle extras) {
-        return AVAILABLE;
-    }
-
-    @Override public boolean getLocation(Location l) {
-        if (mEnabled) {
-            update();
-            l.setProvider(getName());
-            l.setTime(mTime + mBaseTime);
-            l.setLatitude(mLatitude);
-            l.setLongitude(mLongitude);
-            if (mSupportsAltitude && mHasAltitude) {
-                l.setAltitude(mAltitude);
-            }
-            if (mSupportsBearing && mHasBearing) {
-                l.setBearing(mBearing);
-            }
-            if (mSupportsSpeed && mHasSpeed) {
-                l.setSpeed(mSpeed);
-            }
-            if (mExtras != null) {
-                l.setExtras(mExtras);
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    public Location getInitialLocation() {
-        return mInitialLocation;
-    }
-}
-
-/**
- * A simple tuple of (time stamp, latitude, longitude, altitude), plus optional
- * extras.
- *
- * {@hide}
- */
-class Waypoint {
-    public Location mLocation;
-
-    public Waypoint(Location location) {
-        mLocation = location;
-    }
-
-    public Waypoint(String providerName, long time, double latitude, double longitude,
-        double altitude) {
-        mLocation = new Location(providerName);
-        mLocation.setTime(time);
-        mLocation.setLatitude(latitude);
-        mLocation.setLongitude(longitude);
-        mLocation.setAltitude(altitude);
-    }
-
-    public long getTime() {
-        return mLocation.getTime();
-    }
-
-    public double getLatitude() {
-        return mLocation.getLatitude();
-    }
-
-    public double getLongitude() {
-        return mLocation.getLongitude();
-    }
-
-    public boolean hasAltitude() {
-        return mLocation.hasAltitude();
-    }
-
-    public double getAltitude() {
-        return mLocation.getAltitude();
-    }
-
-    public boolean hasBearing() {
-        return mLocation.hasBearing();
-    }
-
-    public void setBearing(float bearing) {
-        mLocation.setBearing(bearing);
-    }
-
-    public float getBearing() {
-        return mLocation.getBearing();
-    }
-
-    public boolean hasSpeed() {
-        return mLocation.hasSpeed();
-    }
-
-    public void setSpeed(float speed) {
-        mLocation.setSpeed(speed);
-    }
-
-    public float getSpeed() {
-        return mLocation.getSpeed();
-    }
-
-    public Bundle getExtras() {
-        return mLocation.getExtras();
-    }
-
-    public Location getLocation() {
-        return new Location(mLocation);
-    }
-
-    @Override public String toString() {
-        return "Waypoint[mLocation=" + mLocation + "]";
-    }
-}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index d0fa795..5917ab90 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -200,7 +200,7 @@
          * param error   error code:
          * - AUDIO_STATUS_OK
          * - AUDIO_STATUS_SERVER_DIED
-         * - UDIO_STATUS_ERROR
+         * - AUDIO_STATUS_ERROR
          */
         void onError(int error);
     };
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index fc8476d..ae3e181 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -453,11 +453,12 @@
                 FileCacheEntry entry = beginFile(path, mimeType, lastModified, fileSize);
                 // rescan for metadata if file was modified since last scan
                 if (entry != null && (entry.mLastModifiedChanged || scanAlways)) {
-                    boolean ringtones = (path.indexOf(RINGTONES_DIR) > 0);
-                    boolean notifications = (path.indexOf(NOTIFICATIONS_DIR) > 0);
-                    boolean alarms = (path.indexOf(ALARMS_DIR) > 0);
-                    boolean podcasts = (path.indexOf(PODCAST_DIR) > 0);
-                    boolean music = (path.indexOf(MUSIC_DIR) > 0) ||
+                    String lowpath = path.toLowerCase();
+                    boolean ringtones = (lowpath.indexOf(RINGTONES_DIR) > 0);
+                    boolean notifications = (lowpath.indexOf(NOTIFICATIONS_DIR) > 0);
+                    boolean alarms = (lowpath.indexOf(ALARMS_DIR) > 0);
+                    boolean podcasts = (lowpath.indexOf(PODCAST_DIR) > 0);
+                    boolean music = (lowpath.indexOf(MUSIC_DIR) > 0) ||
                         (!ringtones && !notifications && !alarms && !podcasts);
 
                     if (mFileType == MediaFile.FILE_TYPE_MP3 ||
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 986f88e..1720af0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -73,7 +73,6 @@
         // Otherwise the callback thread will never exit.
         stop();
         if (mClientRecordThread != 0) {
-            mCblk->cv.signal();
             mClientRecordThread->requestExitAndWait();
             mClientRecordThread.clear();
         }
@@ -96,7 +95,7 @@
 {
 
     LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount);
-    if (mAudioFlinger != 0) {
+    if (mAudioRecord != 0) {
         return INVALID_OPERATION;
     }
 
@@ -181,7 +180,6 @@
 
     mStatus = NO_ERROR;
 
-    mAudioFlinger = audioFlinger;
     mAudioRecord = record;
     mCblkMemory = cblk;
     mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
@@ -293,6 +291,7 @@
      }
 
     if (android_atomic_and(~1, &mActive) == 1) {
+        mCblk->cv.signal();
         mAudioRecord->stop();
         // the record head position will reset to 0, so if a marker is set, we need
         // to activate it again
@@ -375,6 +374,7 @@
     status_t result;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = audioBuffer->frameCount;
+    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
 
     audioBuffer->frameCount  = 0;
     audioBuffer->size        = 0;
@@ -391,9 +391,9 @@
             if (UNLIKELY(!waitCount))
                 return WOULD_BLOCK;
             timeout = 0;
-            result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
             if (__builtin_expect(result!=NO_ERROR, false)) {
-                cblk->waitTimeMs += WAIT_PERIOD_MS;
+                cblk->waitTimeMs += waitTimeMs;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
                     LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
                             "user=%08x, server=%08x", cblk->user, cblk->server);
@@ -520,7 +520,7 @@
         status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
             if (err != TIMED_OUT) {
-                LOGE("Error obtaining an audio buffer, giving up.");
+                LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
                 return false;
             }
             break;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 24f7281..289bd75 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -92,7 +92,6 @@
         // Otherwise the callback thread will never exit.
         stop();
         if (mAudioTrackThread != 0) {
-            mCblk->cv.signal();
             mAudioTrackThread->requestExitAndWait();
             mAudioTrackThread.clear();
         }
@@ -117,7 +116,7 @@
 
     LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
 
-    if (mAudioFlinger != 0) {
+    if (mAudioTrack != 0) {
         LOGE("Track already in use");
         return INVALID_OPERATION;
     }
@@ -228,7 +227,6 @@
 
     mStatus = NO_ERROR;
 
-    mAudioFlinger = audioFlinger;
     mAudioTrack = track;
     mCblkMemory = cblk;
     mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
@@ -357,6 +355,7 @@
     }
 
     if (android_atomic_and(~1, &mActive) == 1) {
+        mCblk->cv.signal();
         mAudioTrack->stop();
         // Cancel loops (If we are in the middle of a loop, playback
         // would not stop until loopCount reaches 0).
@@ -596,6 +595,7 @@
     status_t result;
     audio_track_cblk_t* cblk = mCblk;
     uint32_t framesReq = audioBuffer->frameCount;
+    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
 
     audioBuffer->frameCount  = 0;
     audioBuffer->size = 0;
@@ -614,9 +614,9 @@
             if (UNLIKELY(!waitCount))
                 return WOULD_BLOCK;
             timeout = 0;
-            result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS));
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
             if (__builtin_expect(result!=NO_ERROR, false)) { 
-                cblk->waitTimeMs += WAIT_PERIOD_MS;
+                cblk->waitTimeMs += waitTimeMs;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
                     // timing out when a loop has been set and we have already written upto loop end
                     // is a normal condition: no need to wake AudioFlinger up.
@@ -798,7 +798,7 @@
         status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
             if (err != TIMED_OUT) {
-                LOGE("Error obtaining an audio buffer, giving up.");
+                LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
                 return false;
             }
             break;
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 5cbb25c..52bd7d4 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -336,7 +336,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        remote()->transact(WAKE_UP, data, &reply);
+        remote()->transact(WAKE_UP, data, &reply, IBinder::FLAG_ONEWAY);
         return;
     }
 
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index 5feb11f..9d00aefb 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -43,7 +43,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
         data.writeInt32((int)enabled);
-        remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply);
+        remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index 07b43bb..281828f 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -464,6 +464,7 @@
   public static final String RECORDED_SQVGA_H263 = "/sdcard/SQVGA_H263.3gp";
   public static final String RECORDED_CIF_H263 = "/sdcard/CIF_H263.3gp";
   public static final String RECORDED_QCIF_H263 = "/sdcard/QCIF_H263.3gp";
+  public static final String RECORDED_PORTRAIT_H263 = "/sdcard/QCIF_mp4.3gp";
   
   public static final String RECORDED_HVGA_MP4 = "/sdcard/HVGA_mp4.mp4";
   public static final String RECORDED_QVGA_MP4 = "/sdcard/QVGA_mp4.mp4";
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index 65451c5..261b4f4 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -22,6 +22,7 @@
 import java.io.*;
 
 import android.content.Context;
+import android.hardware.Camera;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
 import android.test.ActivityInstrumentationTestCase;
@@ -46,6 +47,7 @@
     private SurfaceHolder mSurfaceHolder = null;
     private MediaRecorder mRecorder;
     Context mContext;
+    Camera mCamera;
   
     public MediaRecorderTest() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
@@ -234,12 +236,32 @@
         assertTrue("QCIFH263 Video Only", videoRecordedResult);
     }
     
-    @Suppress
-    public void testPortraitH263() throws Exception {       
+    @LargeTest
+    /*
+     * This test case set the camera in portrait mode.
+     * Verification: validate the video dimension and the duration.
+     */
+    public void testPortraitH263() throws Exception {
         boolean videoRecordedResult = false;
-        recordVideo(15, 144, 176, MediaRecorder.VideoEncoder.H263, 
-               MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);      
-        videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 144, 176);
+        try {
+            mCamera = Camera.open();
+            Camera.Parameters parameters = mCamera.getParameters();
+            parameters.setPreviewSize(352, 288);
+            parameters.set("orientation", "portrait");
+            mCamera.setParameters(parameters);
+            mCamera.unlock();
+            mRecorder.setCamera(mCamera);
+            Thread.sleep(1000);
+            recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.H263,
+                    MediaRecorder.OutputFormat.THREE_GPP, 
+                    MediaNames.RECORDED_PORTRAIT_H263, true);
+            videoRecordedResult = 
+                validateVideo(MediaNames.RECORDED_PORTRAIT_H263, 352, 288);
+            mCamera.lock();
+            mCamera.release();
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
         assertTrue("PortraitH263", videoRecordedResult);
     }
     
diff --git a/opengl/java/android/opengl/GLES10.java b/opengl/java/android/opengl/GLES10.java
new file mode 100644
index 0000000..147b60f
--- /dev/null
+++ b/opengl/java/android/opengl/GLES10.java
@@ -0,0 +1,1325 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import java.nio.Buffer;
+
+public class GLES10 {
+    public static final int GL_ADD                                   = 0x0104;
+    public static final int GL_ALIASED_LINE_WIDTH_RANGE              = 0x846E;
+    public static final int GL_ALIASED_POINT_SIZE_RANGE              = 0x846D;
+    public static final int GL_ALPHA                                 = 0x1906;
+    public static final int GL_ALPHA_BITS                            = 0x0D55;
+    public static final int GL_ALPHA_TEST                            = 0x0BC0;
+    public static final int GL_ALWAYS                                = 0x0207;
+    public static final int GL_AMBIENT                               = 0x1200;
+    public static final int GL_AMBIENT_AND_DIFFUSE                   = 0x1602;
+    public static final int GL_AND                                   = 0x1501;
+    public static final int GL_AND_INVERTED                          = 0x1504;
+    public static final int GL_AND_REVERSE                           = 0x1502;
+    public static final int GL_BACK                                  = 0x0405;
+    public static final int GL_BLEND                                 = 0x0BE2;
+    public static final int GL_BLUE_BITS                             = 0x0D54;
+    public static final int GL_BYTE                                  = 0x1400;
+    public static final int GL_CCW                                   = 0x0901;
+    public static final int GL_CLAMP_TO_EDGE                         = 0x812F;
+    public static final int GL_CLEAR                                 = 0x1500;
+    public static final int GL_COLOR_ARRAY                           = 0x8076;
+    public static final int GL_COLOR_BUFFER_BIT                      = 0x4000;
+    public static final int GL_COLOR_LOGIC_OP                        = 0x0BF2;
+    public static final int GL_COLOR_MATERIAL                        = 0x0B57;
+    public static final int GL_COMPRESSED_TEXTURE_FORMATS            = 0x86A3;
+    public static final int GL_CONSTANT_ATTENUATION                  = 0x1207;
+    public static final int GL_COPY                                  = 0x1503;
+    public static final int GL_COPY_INVERTED                         = 0x150C;
+    public static final int GL_CULL_FACE                             = 0x0B44;
+    public static final int GL_CW                                    = 0x0900;
+    public static final int GL_DECAL                                 = 0x2101;
+    public static final int GL_DECR                                  = 0x1E03;
+    public static final int GL_DEPTH_BITS                            = 0x0D56;
+    public static final int GL_DEPTH_BUFFER_BIT                      = 0x0100;
+    public static final int GL_DEPTH_TEST                            = 0x0B71;
+    public static final int GL_DIFFUSE                               = 0x1201;
+    public static final int GL_DITHER                                = 0x0BD0;
+    public static final int GL_DONT_CARE                             = 0x1100;
+    public static final int GL_DST_ALPHA                             = 0x0304;
+    public static final int GL_DST_COLOR                             = 0x0306;
+    public static final int GL_EMISSION                              = 0x1600;
+    public static final int GL_EQUAL                                 = 0x0202;
+    public static final int GL_EQUIV                                 = 0x1509;
+    public static final int GL_EXP                                   = 0x0800;
+    public static final int GL_EXP2                                  = 0x0801;
+    public static final int GL_EXTENSIONS                            = 0x1F03;
+    public static final int GL_FALSE                                 = 0;
+    public static final int GL_FASTEST                               = 0x1101;
+    public static final int GL_FIXED                                 = 0x140C;
+    public static final int GL_FLAT                                  = 0x1D00;
+    public static final int GL_FLOAT                                 = 0x1406;
+    public static final int GL_FOG                                   = 0x0B60;
+    public static final int GL_FOG_COLOR                             = 0x0B66;
+    public static final int GL_FOG_DENSITY                           = 0x0B62;
+    public static final int GL_FOG_END                               = 0x0B64;
+    public static final int GL_FOG_HINT                              = 0x0C54;
+    public static final int GL_FOG_MODE                              = 0x0B65;
+    public static final int GL_FOG_START                             = 0x0B63;
+    public static final int GL_FRONT                                 = 0x0404;
+    public static final int GL_FRONT_AND_BACK                        = 0x0408;
+    public static final int GL_GEQUAL                                = 0x0206;
+    public static final int GL_GREATER                               = 0x0204;
+    public static final int GL_GREEN_BITS                            = 0x0D53;
+    public static final int GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES  = 0x8B9B;
+    public static final int GL_IMPLEMENTATION_COLOR_READ_TYPE_OES    = 0x8B9A;
+    public static final int GL_INCR                                  = 0x1E02;
+    public static final int GL_INVALID_ENUM                          = 0x0500;
+    public static final int GL_INVALID_OPERATION                     = 0x0502;
+    public static final int GL_INVALID_VALUE                         = 0x0501;
+    public static final int GL_INVERT                                = 0x150A;
+    public static final int GL_KEEP                                  = 0x1E00;
+    public static final int GL_LEQUAL                                = 0x0203;
+    public static final int GL_LESS                                  = 0x0201;
+    public static final int GL_LIGHT_MODEL_AMBIENT                   = 0x0B53;
+    public static final int GL_LIGHT_MODEL_TWO_SIDE                  = 0x0B52;
+    public static final int GL_LIGHT0                                = 0x4000;
+    public static final int GL_LIGHT1                                = 0x4001;
+    public static final int GL_LIGHT2                                = 0x4002;
+    public static final int GL_LIGHT3                                = 0x4003;
+    public static final int GL_LIGHT4                                = 0x4004;
+    public static final int GL_LIGHT5                                = 0x4005;
+    public static final int GL_LIGHT6                                = 0x4006;
+    public static final int GL_LIGHT7                                = 0x4007;
+    public static final int GL_LIGHTING                              = 0x0B50;
+    public static final int GL_LINE_LOOP                             = 0x0002;
+    public static final int GL_LINE_SMOOTH                           = 0x0B20;
+    public static final int GL_LINE_SMOOTH_HINT                      = 0x0C52;
+    public static final int GL_LINE_STRIP                            = 0x0003;
+    public static final int GL_LINEAR                                = 0x2601;
+    public static final int GL_LINEAR_ATTENUATION                    = 0x1208;
+    public static final int GL_LINEAR_MIPMAP_LINEAR                  = 0x2703;
+    public static final int GL_LINEAR_MIPMAP_NEAREST                 = 0x2701;
+    public static final int GL_LINES                                 = 0x0001;
+    public static final int GL_LUMINANCE                             = 0x1909;
+    public static final int GL_LUMINANCE_ALPHA                       = 0x190A;
+    public static final int GL_MAX_ELEMENTS_INDICES                  = 0x80E9;
+    public static final int GL_MAX_ELEMENTS_VERTICES                 = 0x80E8;
+    public static final int GL_MAX_LIGHTS                            = 0x0D31;
+    public static final int GL_MAX_MODELVIEW_STACK_DEPTH             = 0x0D36;
+    public static final int GL_MAX_PROJECTION_STACK_DEPTH            = 0x0D38;
+    public static final int GL_MAX_TEXTURE_SIZE                      = 0x0D33;
+    public static final int GL_MAX_TEXTURE_STACK_DEPTH               = 0x0D39;
+    public static final int GL_MAX_TEXTURE_UNITS                     = 0x84E2;
+    public static final int GL_MAX_VIEWPORT_DIMS                     = 0x0D3A;
+    public static final int GL_MODELVIEW                             = 0x1700;
+    public static final int GL_MODULATE                              = 0x2100;
+    public static final int GL_MULTISAMPLE                           = 0x809D;
+    public static final int GL_NAND                                  = 0x150E;
+    public static final int GL_NEAREST                               = 0x2600;
+    public static final int GL_NEAREST_MIPMAP_LINEAR                 = 0x2702;
+    public static final int GL_NEAREST_MIPMAP_NEAREST                = 0x2700;
+    public static final int GL_NEVER                                 = 0x0200;
+    public static final int GL_NICEST                                = 0x1102;
+    public static final int GL_NO_ERROR                              = 0;
+    public static final int GL_NOOP                                  = 0x1505;
+    public static final int GL_NOR                                   = 0x1508;
+    public static final int GL_NORMAL_ARRAY                          = 0x8075;
+    public static final int GL_NORMALIZE                             = 0x0BA1;
+    public static final int GL_NOTEQUAL                              = 0x0205;
+    public static final int GL_NUM_COMPRESSED_TEXTURE_FORMATS        = 0x86A2;
+    public static final int GL_ONE                                   = 1;
+    public static final int GL_ONE_MINUS_DST_ALPHA                   = 0x0305;
+    public static final int GL_ONE_MINUS_DST_COLOR                   = 0x0307;
+    public static final int GL_ONE_MINUS_SRC_ALPHA                   = 0x0303;
+    public static final int GL_ONE_MINUS_SRC_COLOR                   = 0x0301;
+    public static final int GL_OR                                    = 0x1507;
+    public static final int GL_OR_INVERTED                           = 0x150D;
+    public static final int GL_OR_REVERSE                            = 0x150B;
+    public static final int GL_OUT_OF_MEMORY                         = 0x0505;
+    public static final int GL_PACK_ALIGNMENT                        = 0x0D05;
+    public static final int GL_PALETTE4_R5_G6_B5_OES                 = 0x8B92;
+    public static final int GL_PALETTE4_RGB5_A1_OES                  = 0x8B94;
+    public static final int GL_PALETTE4_RGB8_OES                     = 0x8B90;
+    public static final int GL_PALETTE4_RGBA4_OES                    = 0x8B93;
+    public static final int GL_PALETTE4_RGBA8_OES                    = 0x8B91;
+    public static final int GL_PALETTE8_R5_G6_B5_OES                 = 0x8B97;
+    public static final int GL_PALETTE8_RGB5_A1_OES                  = 0x8B99;
+    public static final int GL_PALETTE8_RGB8_OES                     = 0x8B95;
+    public static final int GL_PALETTE8_RGBA4_OES                    = 0x8B98;
+    public static final int GL_PALETTE8_RGBA8_OES                    = 0x8B96;
+    public static final int GL_PERSPECTIVE_CORRECTION_HINT           = 0x0C50;
+    public static final int GL_POINT_SMOOTH                          = 0x0B10;
+    public static final int GL_POINT_SMOOTH_HINT                     = 0x0C51;
+    public static final int GL_POINTS                                = 0x0000;
+    public static final int GL_POINT_FADE_THRESHOLD_SIZE             = 0x8128;
+    public static final int GL_POINT_SIZE                            = 0x0B11;
+    public static final int GL_POLYGON_OFFSET_FILL                   = 0x8037;
+    public static final int GL_POLYGON_SMOOTH_HINT                   = 0x0C53;
+    public static final int GL_POSITION                              = 0x1203;
+    public static final int GL_PROJECTION                            = 0x1701;
+    public static final int GL_QUADRATIC_ATTENUATION                 = 0x1209;
+    public static final int GL_RED_BITS                              = 0x0D52;
+    public static final int GL_RENDERER                              = 0x1F01;
+    public static final int GL_REPEAT                                = 0x2901;
+    public static final int GL_REPLACE                               = 0x1E01;
+    public static final int GL_RESCALE_NORMAL                        = 0x803A;
+    public static final int GL_RGB                                   = 0x1907;
+    public static final int GL_RGBA                                  = 0x1908;
+    public static final int GL_SAMPLE_ALPHA_TO_COVERAGE              = 0x809E;
+    public static final int GL_SAMPLE_ALPHA_TO_ONE                   = 0x809F;
+    public static final int GL_SAMPLE_COVERAGE                       = 0x80A0;
+    public static final int GL_SCISSOR_TEST                          = 0x0C11;
+    public static final int GL_SET                                   = 0x150F;
+    public static final int GL_SHININESS                             = 0x1601;
+    public static final int GL_SHORT                                 = 0x1402;
+    public static final int GL_SMOOTH                                = 0x1D01;
+    public static final int GL_SMOOTH_LINE_WIDTH_RANGE               = 0x0B22;
+    public static final int GL_SMOOTH_POINT_SIZE_RANGE               = 0x0B12;
+    public static final int GL_SPECULAR                              = 0x1202;
+    public static final int GL_SPOT_CUTOFF                           = 0x1206;
+    public static final int GL_SPOT_DIRECTION                        = 0x1204;
+    public static final int GL_SPOT_EXPONENT                         = 0x1205;
+    public static final int GL_SRC_ALPHA                             = 0x0302;
+    public static final int GL_SRC_ALPHA_SATURATE                    = 0x0308;
+    public static final int GL_SRC_COLOR                             = 0x0300;
+    public static final int GL_STACK_OVERFLOW                        = 0x0503;
+    public static final int GL_STACK_UNDERFLOW                       = 0x0504;
+    public static final int GL_STENCIL_BITS                          = 0x0D57;
+    public static final int GL_STENCIL_BUFFER_BIT                    = 0x0400;
+    public static final int GL_STENCIL_TEST                          = 0x0B90;
+    public static final int GL_SUBPIXEL_BITS                         = 0x0D50;
+    public static final int GL_TEXTURE                               = 0x1702;
+    public static final int GL_TEXTURE_2D                            = 0x0DE1;
+    public static final int GL_TEXTURE_COORD_ARRAY                   = 0x8078;
+    public static final int GL_TEXTURE_ENV                           = 0x2300;
+    public static final int GL_TEXTURE_ENV_COLOR                     = 0x2201;
+    public static final int GL_TEXTURE_ENV_MODE                      = 0x2200;
+    public static final int GL_TEXTURE_MAG_FILTER                    = 0x2800;
+    public static final int GL_TEXTURE_MIN_FILTER                    = 0x2801;
+    public static final int GL_TEXTURE_WRAP_S                        = 0x2802;
+    public static final int GL_TEXTURE_WRAP_T                        = 0x2803;
+    public static final int GL_TEXTURE0                              = 0x84C0;
+    public static final int GL_TEXTURE1                              = 0x84C1;
+    public static final int GL_TEXTURE2                              = 0x84C2;
+    public static final int GL_TEXTURE3                              = 0x84C3;
+    public static final int GL_TEXTURE4                              = 0x84C4;
+    public static final int GL_TEXTURE5                              = 0x84C5;
+    public static final int GL_TEXTURE6                              = 0x84C6;
+    public static final int GL_TEXTURE7                              = 0x84C7;
+    public static final int GL_TEXTURE8                              = 0x84C8;
+    public static final int GL_TEXTURE9                              = 0x84C9;
+    public static final int GL_TEXTURE10                             = 0x84CA;
+    public static final int GL_TEXTURE11                             = 0x84CB;
+    public static final int GL_TEXTURE12                             = 0x84CC;
+    public static final int GL_TEXTURE13                             = 0x84CD;
+    public static final int GL_TEXTURE14                             = 0x84CE;
+    public static final int GL_TEXTURE15                             = 0x84CF;
+    public static final int GL_TEXTURE16                             = 0x84D0;
+    public static final int GL_TEXTURE17                             = 0x84D1;
+    public static final int GL_TEXTURE18                             = 0x84D2;
+    public static final int GL_TEXTURE19                             = 0x84D3;
+    public static final int GL_TEXTURE20                             = 0x84D4;
+    public static final int GL_TEXTURE21                             = 0x84D5;
+    public static final int GL_TEXTURE22                             = 0x84D6;
+    public static final int GL_TEXTURE23                             = 0x84D7;
+    public static final int GL_TEXTURE24                             = 0x84D8;
+    public static final int GL_TEXTURE25                             = 0x84D9;
+    public static final int GL_TEXTURE26                             = 0x84DA;
+    public static final int GL_TEXTURE27                             = 0x84DB;
+    public static final int GL_TEXTURE28                             = 0x84DC;
+    public static final int GL_TEXTURE29                             = 0x84DD;
+    public static final int GL_TEXTURE30                             = 0x84DE;
+    public static final int GL_TEXTURE31                             = 0x84DF;
+    public static final int GL_TRIANGLE_FAN                          = 0x0006;
+    public static final int GL_TRIANGLE_STRIP                        = 0x0005;
+    public static final int GL_TRIANGLES                             = 0x0004;
+    public static final int GL_TRUE                                  = 1;
+    public static final int GL_UNPACK_ALIGNMENT                      = 0x0CF5;
+    public static final int GL_UNSIGNED_BYTE                         = 0x1401;
+    public static final int GL_UNSIGNED_SHORT                        = 0x1403;
+    public static final int GL_UNSIGNED_SHORT_4_4_4_4                = 0x8033;
+    public static final int GL_UNSIGNED_SHORT_5_5_5_1                = 0x8034;
+    public static final int GL_UNSIGNED_SHORT_5_6_5                  = 0x8363;
+    public static final int GL_VENDOR                                = 0x1F00;
+    public static final int GL_VERSION                               = 0x1F02;
+    public static final int GL_VERTEX_ARRAY                          = 0x8074;
+    public static final int GL_XOR                                   = 0x1506;
+    public static final int GL_ZERO                                  = 0;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+
+    private static Buffer _colorPointer;
+    private static Buffer _normalPointer;
+    private static Buffer _texCoordPointer;
+    private static Buffer _vertexPointer;
+
+    // C function void glActiveTexture ( GLenum texture )
+
+    public static native void glActiveTexture(
+        int texture
+    );
+
+    // C function void glAlphaFunc ( GLenum func, GLclampf ref )
+
+    public static native void glAlphaFunc(
+        int func,
+        float ref
+    );
+
+    // C function void glAlphaFuncx ( GLenum func, GLclampx ref )
+
+    public static native void glAlphaFuncx(
+        int func,
+        int ref
+    );
+
+    // C function void glBindTexture ( GLenum target, GLuint texture )
+
+    public static native void glBindTexture(
+        int target,
+        int texture
+    );
+
+    // C function void glBlendFunc ( GLenum sfactor, GLenum dfactor )
+
+    public static native void glBlendFunc(
+        int sfactor,
+        int dfactor
+    );
+
+    // C function void glClear ( GLbitfield mask )
+
+    public static native void glClear(
+        int mask
+    );
+
+    // C function void glClearColor ( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+
+    public static native void glClearColor(
+        float red,
+        float green,
+        float blue,
+        float alpha
+    );
+
+    // C function void glClearColorx ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha )
+
+    public static native void glClearColorx(
+        int red,
+        int green,
+        int blue,
+        int alpha
+    );
+
+    // C function void glClearDepthf ( GLclampf depth )
+
+    public static native void glClearDepthf(
+        float depth
+    );
+
+    // C function void glClearDepthx ( GLclampx depth )
+
+    public static native void glClearDepthx(
+        int depth
+    );
+
+    // C function void glClearStencil ( GLint s )
+
+    public static native void glClearStencil(
+        int s
+    );
+
+    // C function void glClientActiveTexture ( GLenum texture )
+
+    public static native void glClientActiveTexture(
+        int texture
+    );
+
+    // C function void glColor4f ( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+
+    public static native void glColor4f(
+        float red,
+        float green,
+        float blue,
+        float alpha
+    );
+
+    // C function void glColor4x ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha )
+
+    public static native void glColor4x(
+        int red,
+        int green,
+        int blue,
+        int alpha
+    );
+
+    // C function void glColorMask ( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha )
+
+    public static native void glColorMask(
+        boolean red,
+        boolean green,
+        boolean blue,
+        boolean alpha
+    );
+
+    // C function void glColorPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+
+    private static native void glColorPointerBounds(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer,
+        int remaining
+    );
+
+    public static void glColorPointer(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer
+    ) {
+        if ((size == 4) &&
+            ((type == GL_FLOAT) ||
+             (type == GL_UNSIGNED_BYTE) ||
+             (type == GL_FIXED)) &&
+            (stride >= 0)) {
+            _colorPointer = pointer;
+        }
+        glColorPointerBounds(
+            size,
+            type,
+            stride,
+            pointer,
+            pointer.remaining()
+        );
+    }
+
+    // C function void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data )
+
+    public static native void glCompressedTexImage2D(
+        int target,
+        int level,
+        int internalformat,
+        int width,
+        int height,
+        int border,
+        int imageSize,
+        java.nio.Buffer data
+    );
+
+    // C function void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data )
+
+    public static native void glCompressedTexSubImage2D(
+        int target,
+        int level,
+        int xoffset,
+        int yoffset,
+        int width,
+        int height,
+        int format,
+        int imageSize,
+        java.nio.Buffer data
+    );
+
+    // C function void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
+
+    public static native void glCopyTexImage2D(
+        int target,
+        int level,
+        int internalformat,
+        int x,
+        int y,
+        int width,
+        int height,
+        int border
+    );
+
+    // C function void glCopyTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
+
+    public static native void glCopyTexSubImage2D(
+        int target,
+        int level,
+        int xoffset,
+        int yoffset,
+        int x,
+        int y,
+        int width,
+        int height
+    );
+
+    // C function void glCullFace ( GLenum mode )
+
+    public static native void glCullFace(
+        int mode
+    );
+
+    // C function void glDeleteTextures ( GLsizei n, const GLuint *textures )
+
+    public static native void glDeleteTextures(
+        int n,
+        int[] textures,
+        int offset
+    );
+
+    // C function void glDeleteTextures ( GLsizei n, const GLuint *textures )
+
+    public static native void glDeleteTextures(
+        int n,
+        java.nio.IntBuffer textures
+    );
+
+    // C function void glDepthFunc ( GLenum func )
+
+    public static native void glDepthFunc(
+        int func
+    );
+
+    // C function void glDepthMask ( GLboolean flag )
+
+    public static native void glDepthMask(
+        boolean flag
+    );
+
+    // C function void glDepthRangef ( GLclampf zNear, GLclampf zFar )
+
+    public static native void glDepthRangef(
+        float zNear,
+        float zFar
+    );
+
+    // C function void glDepthRangex ( GLclampx zNear, GLclampx zFar )
+
+    public static native void glDepthRangex(
+        int zNear,
+        int zFar
+    );
+
+    // C function void glDisable ( GLenum cap )
+
+    public static native void glDisable(
+        int cap
+    );
+
+    // C function void glDisableClientState ( GLenum array )
+
+    public static native void glDisableClientState(
+        int array
+    );
+
+    // C function void glDrawArrays ( GLenum mode, GLint first, GLsizei count )
+
+    public static native void glDrawArrays(
+        int mode,
+        int first,
+        int count
+    );
+
+    // C function void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
+
+    public static native void glDrawElements(
+        int mode,
+        int count,
+        int type,
+        java.nio.Buffer indices
+    );
+
+    // C function void glEnable ( GLenum cap )
+
+    public static native void glEnable(
+        int cap
+    );
+
+    // C function void glEnableClientState ( GLenum array )
+
+    public static native void glEnableClientState(
+        int array
+    );
+
+    // C function void glFinish ( void )
+
+    public static native void glFinish(
+    );
+
+    // C function void glFlush ( void )
+
+    public static native void glFlush(
+    );
+
+    // C function void glFogf ( GLenum pname, GLfloat param )
+
+    public static native void glFogf(
+        int pname,
+        float param
+    );
+
+    // C function void glFogfv ( GLenum pname, const GLfloat *params )
+
+    public static native void glFogfv(
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glFogfv ( GLenum pname, const GLfloat *params )
+
+    public static native void glFogfv(
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glFogx ( GLenum pname, GLfixed param )
+
+    public static native void glFogx(
+        int pname,
+        int param
+    );
+
+    // C function void glFogxv ( GLenum pname, const GLfixed *params )
+
+    public static native void glFogxv(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glFogxv ( GLenum pname, const GLfixed *params )
+
+    public static native void glFogxv(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glFrontFace ( GLenum mode )
+
+    public static native void glFrontFace(
+        int mode
+    );
+
+    // C function void glFrustumf ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+
+    public static native void glFrustumf(
+        float left,
+        float right,
+        float bottom,
+        float top,
+        float zNear,
+        float zFar
+    );
+
+    // C function void glFrustumx ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+
+    public static native void glFrustumx(
+        int left,
+        int right,
+        int bottom,
+        int top,
+        int zNear,
+        int zFar
+    );
+
+    // C function void glGenTextures ( GLsizei n, GLuint *textures )
+
+    public static native void glGenTextures(
+        int n,
+        int[] textures,
+        int offset
+    );
+
+    // C function void glGenTextures ( GLsizei n, GLuint *textures )
+
+    public static native void glGenTextures(
+        int n,
+        java.nio.IntBuffer textures
+    );
+
+    // C function GLenum glGetError ( void )
+
+    public static native int glGetError(
+    );
+
+    // C function void glGetIntegerv ( GLenum pname, GLint *params )
+
+    public static native void glGetIntegerv(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetIntegerv ( GLenum pname, GLint *params )
+
+    public static native void glGetIntegerv(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function const GLubyte * glGetString ( GLenum name )
+
+    public static native String glGetString(
+        int name
+    );
+    // C function void glHint ( GLenum target, GLenum mode )
+
+    public static native void glHint(
+        int target,
+        int mode
+    );
+
+    // C function void glLightModelf ( GLenum pname, GLfloat param )
+
+    public static native void glLightModelf(
+        int pname,
+        float param
+    );
+
+    // C function void glLightModelfv ( GLenum pname, const GLfloat *params )
+
+    public static native void glLightModelfv(
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glLightModelfv ( GLenum pname, const GLfloat *params )
+
+    public static native void glLightModelfv(
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glLightModelx ( GLenum pname, GLfixed param )
+
+    public static native void glLightModelx(
+        int pname,
+        int param
+    );
+
+    // C function void glLightModelxv ( GLenum pname, const GLfixed *params )
+
+    public static native void glLightModelxv(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glLightModelxv ( GLenum pname, const GLfixed *params )
+
+    public static native void glLightModelxv(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glLightf ( GLenum light, GLenum pname, GLfloat param )
+
+    public static native void glLightf(
+        int light,
+        int pname,
+        float param
+    );
+
+    // C function void glLightfv ( GLenum light, GLenum pname, const GLfloat *params )
+
+    public static native void glLightfv(
+        int light,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glLightfv ( GLenum light, GLenum pname, const GLfloat *params )
+
+    public static native void glLightfv(
+        int light,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glLightx ( GLenum light, GLenum pname, GLfixed param )
+
+    public static native void glLightx(
+        int light,
+        int pname,
+        int param
+    );
+
+    // C function void glLightxv ( GLenum light, GLenum pname, const GLfixed *params )
+
+    public static native void glLightxv(
+        int light,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glLightxv ( GLenum light, GLenum pname, const GLfixed *params )
+
+    public static native void glLightxv(
+        int light,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glLineWidth ( GLfloat width )
+
+    public static native void glLineWidth(
+        float width
+    );
+
+    // C function void glLineWidthx ( GLfixed width )
+
+    public static native void glLineWidthx(
+        int width
+    );
+
+    // C function void glLoadIdentity ( void )
+
+    public static native void glLoadIdentity(
+    );
+
+    // C function void glLoadMatrixf ( const GLfloat *m )
+
+    public static native void glLoadMatrixf(
+        float[] m,
+        int offset
+    );
+
+    // C function void glLoadMatrixf ( const GLfloat *m )
+
+    public static native void glLoadMatrixf(
+        java.nio.FloatBuffer m
+    );
+
+    // C function void glLoadMatrixx ( const GLfixed *m )
+
+    public static native void glLoadMatrixx(
+        int[] m,
+        int offset
+    );
+
+    // C function void glLoadMatrixx ( const GLfixed *m )
+
+    public static native void glLoadMatrixx(
+        java.nio.IntBuffer m
+    );
+
+    // C function void glLogicOp ( GLenum opcode )
+
+    public static native void glLogicOp(
+        int opcode
+    );
+
+    // C function void glMaterialf ( GLenum face, GLenum pname, GLfloat param )
+
+    public static native void glMaterialf(
+        int face,
+        int pname,
+        float param
+    );
+
+    // C function void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params )
+
+    public static native void glMaterialfv(
+        int face,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params )
+
+    public static native void glMaterialfv(
+        int face,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glMaterialx ( GLenum face, GLenum pname, GLfixed param )
+
+    public static native void glMaterialx(
+        int face,
+        int pname,
+        int param
+    );
+
+    // C function void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params )
+
+    public static native void glMaterialxv(
+        int face,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params )
+
+    public static native void glMaterialxv(
+        int face,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glMatrixMode ( GLenum mode )
+
+    public static native void glMatrixMode(
+        int mode
+    );
+
+    // C function void glMultMatrixf ( const GLfloat *m )
+
+    public static native void glMultMatrixf(
+        float[] m,
+        int offset
+    );
+
+    // C function void glMultMatrixf ( const GLfloat *m )
+
+    public static native void glMultMatrixf(
+        java.nio.FloatBuffer m
+    );
+
+    // C function void glMultMatrixx ( const GLfixed *m )
+
+    public static native void glMultMatrixx(
+        int[] m,
+        int offset
+    );
+
+    // C function void glMultMatrixx ( const GLfixed *m )
+
+    public static native void glMultMatrixx(
+        java.nio.IntBuffer m
+    );
+
+    // C function void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q )
+
+    public static native void glMultiTexCoord4f(
+        int target,
+        float s,
+        float t,
+        float r,
+        float q
+    );
+
+    // C function void glMultiTexCoord4x ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q )
+
+    public static native void glMultiTexCoord4x(
+        int target,
+        int s,
+        int t,
+        int r,
+        int q
+    );
+
+    // C function void glNormal3f ( GLfloat nx, GLfloat ny, GLfloat nz )
+
+    public static native void glNormal3f(
+        float nx,
+        float ny,
+        float nz
+    );
+
+    // C function void glNormal3x ( GLfixed nx, GLfixed ny, GLfixed nz )
+
+    public static native void glNormal3x(
+        int nx,
+        int ny,
+        int nz
+    );
+
+    // C function void glNormalPointer ( GLenum type, GLsizei stride, const GLvoid *pointer )
+
+    private static native void glNormalPointerBounds(
+        int type,
+        int stride,
+        java.nio.Buffer pointer,
+        int remaining
+    );
+
+    public static void glNormalPointer(
+        int type,
+        int stride,
+        java.nio.Buffer pointer
+    ) {
+        if (((type == GL_FLOAT) ||
+             (type == GL_BYTE) ||
+             (type == GL_SHORT) ||
+             (type == GL_FIXED)) &&
+            (stride >= 0)) {
+            _normalPointer = pointer;
+        }
+        glNormalPointerBounds(
+            type,
+            stride,
+            pointer,
+            pointer.remaining()
+        );
+    }
+
+    // C function void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+
+    public static native void glOrthof(
+        float left,
+        float right,
+        float bottom,
+        float top,
+        float zNear,
+        float zFar
+    );
+
+    // C function void glOrthox ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+
+    public static native void glOrthox(
+        int left,
+        int right,
+        int bottom,
+        int top,
+        int zNear,
+        int zFar
+    );
+
+    // C function void glPixelStorei ( GLenum pname, GLint param )
+
+    public static native void glPixelStorei(
+        int pname,
+        int param
+    );
+
+    // C function void glPointSize ( GLfloat size )
+
+    public static native void glPointSize(
+        float size
+    );
+
+    // C function void glPointSizex ( GLfixed size )
+
+    public static native void glPointSizex(
+        int size
+    );
+
+    // C function void glPolygonOffset ( GLfloat factor, GLfloat units )
+
+    public static native void glPolygonOffset(
+        float factor,
+        float units
+    );
+
+    // C function void glPolygonOffsetx ( GLfixed factor, GLfixed units )
+
+    public static native void glPolygonOffsetx(
+        int factor,
+        int units
+    );
+
+    // C function void glPopMatrix ( void )
+
+    public static native void glPopMatrix(
+    );
+
+    // C function void glPushMatrix ( void )
+
+    public static native void glPushMatrix(
+    );
+
+    // C function void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels )
+
+    public static native void glReadPixels(
+        int x,
+        int y,
+        int width,
+        int height,
+        int format,
+        int type,
+        java.nio.Buffer pixels
+    );
+
+    // C function void glRotatef ( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
+
+    public static native void glRotatef(
+        float angle,
+        float x,
+        float y,
+        float z
+    );
+
+    // C function void glRotatex ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z )
+
+    public static native void glRotatex(
+        int angle,
+        int x,
+        int y,
+        int z
+    );
+
+    // C function void glSampleCoverage ( GLclampf value, GLboolean invert )
+
+    public static native void glSampleCoverage(
+        float value,
+        boolean invert
+    );
+
+    // C function void glSampleCoveragex ( GLclampx value, GLboolean invert )
+
+    public static native void glSampleCoveragex(
+        int value,
+        boolean invert
+    );
+
+    // C function void glScalef ( GLfloat x, GLfloat y, GLfloat z )
+
+    public static native void glScalef(
+        float x,
+        float y,
+        float z
+    );
+
+    // C function void glScalex ( GLfixed x, GLfixed y, GLfixed z )
+
+    public static native void glScalex(
+        int x,
+        int y,
+        int z
+    );
+
+    // C function void glScissor ( GLint x, GLint y, GLsizei width, GLsizei height )
+
+    public static native void glScissor(
+        int x,
+        int y,
+        int width,
+        int height
+    );
+
+    // C function void glShadeModel ( GLenum mode )
+
+    public static native void glShadeModel(
+        int mode
+    );
+
+    // C function void glStencilFunc ( GLenum func, GLint ref, GLuint mask )
+
+    public static native void glStencilFunc(
+        int func,
+        int ref,
+        int mask
+    );
+
+    // C function void glStencilMask ( GLuint mask )
+
+    public static native void glStencilMask(
+        int mask
+    );
+
+    // C function void glStencilOp ( GLenum fail, GLenum zfail, GLenum zpass )
+
+    public static native void glStencilOp(
+        int fail,
+        int zfail,
+        int zpass
+    );
+
+    // C function void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+
+    private static native void glTexCoordPointerBounds(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer,
+        int remaining
+    );
+
+    public static void glTexCoordPointer(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer
+    ) {
+        if (((size == 2) ||
+             (size == 3) ||
+             (size == 4)) &&
+            ((type == GL_FLOAT) ||
+             (type == GL_BYTE) ||
+             (type == GL_SHORT) ||
+             (type == GL_FIXED)) &&
+            (stride >= 0)) {
+            _texCoordPointer = pointer;
+        }
+        glTexCoordPointerBounds(
+            size,
+            type,
+            stride,
+            pointer,
+            pointer.remaining()
+        );
+    }
+
+    // C function void glTexEnvf ( GLenum target, GLenum pname, GLfloat param )
+
+    public static native void glTexEnvf(
+        int target,
+        int pname,
+        float param
+    );
+
+    // C function void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params )
+
+    public static native void glTexEnvfv(
+        int target,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params )
+
+    public static native void glTexEnvfv(
+        int target,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glTexEnvx ( GLenum target, GLenum pname, GLfixed param )
+
+    public static native void glTexEnvx(
+        int target,
+        int pname,
+        int param
+    );
+
+    // C function void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexEnvxv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexEnvxv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
+
+    public static native void glTexImage2D(
+        int target,
+        int level,
+        int internalformat,
+        int width,
+        int height,
+        int border,
+        int format,
+        int type,
+        java.nio.Buffer pixels
+    );
+
+    // C function void glTexParameterf ( GLenum target, GLenum pname, GLfloat param )
+
+    public static native void glTexParameterf(
+        int target,
+        int pname,
+        float param
+    );
+
+    // C function void glTexParameterx ( GLenum target, GLenum pname, GLfixed param )
+
+    public static native void glTexParameterx(
+        int target,
+        int pname,
+        int param
+    );
+
+    // C function void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels )
+
+    public static native void glTexSubImage2D(
+        int target,
+        int level,
+        int xoffset,
+        int yoffset,
+        int width,
+        int height,
+        int format,
+        int type,
+        java.nio.Buffer pixels
+    );
+
+    // C function void glTranslatef ( GLfloat x, GLfloat y, GLfloat z )
+
+    public static native void glTranslatef(
+        float x,
+        float y,
+        float z
+    );
+
+    // C function void glTranslatex ( GLfixed x, GLfixed y, GLfixed z )
+
+    public static native void glTranslatex(
+        int x,
+        int y,
+        int z
+    );
+
+    // C function void glVertexPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+
+    private static native void glVertexPointerBounds(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer,
+        int remaining
+    );
+
+    public static void glVertexPointer(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer
+    ) {
+        if (((size == 2) ||
+             (size == 3) ||
+             (size == 4)) &&
+            ((type == GL_FLOAT) ||
+             (type == GL_BYTE) ||
+             (type == GL_SHORT) ||
+             (type == GL_FIXED)) &&
+            (stride >= 0)) {
+            _vertexPointer = pointer;
+        }
+        glVertexPointerBounds(
+            size,
+            type,
+            stride,
+            pointer,
+            pointer.remaining()
+        );
+    }
+
+    // C function void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height )
+
+    public static native void glViewport(
+        int x,
+        int y,
+        int width,
+        int height
+    );
+
+}
diff --git a/opengl/java/android/opengl/GLES10Ext.java b/opengl/java/android/opengl/GLES10Ext.java
new file mode 100644
index 0000000..81fc59e
--- /dev/null
+++ b/opengl/java/android/opengl/GLES10Ext.java
@@ -0,0 +1,44 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+public class GLES10Ext {
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+    
+    // C function GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent )
+
+    public static native int glQueryMatrixxOES(
+        int[] mantissa,
+        int mantissaOffset,
+        int[] exponent,
+        int exponentOffset
+    );
+
+    // C function GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent )
+
+    public static native int glQueryMatrixxOES(
+        java.nio.IntBuffer mantissa,
+        java.nio.IntBuffer exponent
+    );
+
+}
diff --git a/opengl/java/android/opengl/GLES11.java b/opengl/java/android/opengl/GLES11.java
new file mode 100644
index 0000000..3399af7
--- /dev/null
+++ b/opengl/java/android/opengl/GLES11.java
@@ -0,0 +1,707 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import java.nio.Buffer;
+
+public class GLES11 extends GLES10 {
+    public static final int GL_ACTIVE_TEXTURE                          = 0x84E0;
+    public static final int GL_ADD_SIGNED                              = 0x8574;
+    public static final int GL_ALPHA_SCALE                             = 0x0D1C;
+    public static final int GL_ALPHA_TEST_FUNC                         = 0x0BC1;
+    public static final int GL_ALPHA_TEST_REF                          = 0x0BC2;
+    public static final int GL_ARRAY_BUFFER                            = 0x8892;
+    public static final int GL_ARRAY_BUFFER_BINDING                    = 0x8894;
+    public static final int GL_BLEND_DST                               = 0x0BE0;
+    public static final int GL_BLEND_SRC                               = 0x0BE1;
+    public static final int GL_BUFFER_ACCESS                           = 0x88BB;
+    public static final int GL_BUFFER_SIZE                             = 0x8764;
+    public static final int GL_BUFFER_USAGE                            = 0x8765;
+    public static final int GL_CLIENT_ACTIVE_TEXTURE                   = 0x84E1;
+    public static final int GL_CLIP_PLANE0                             = 0x3000;
+    public static final int GL_CLIP_PLANE1                             = 0x3001;
+    public static final int GL_CLIP_PLANE2                             = 0x3002;
+    public static final int GL_CLIP_PLANE3                             = 0x3003;
+    public static final int GL_CLIP_PLANE4                             = 0x3004;
+    public static final int GL_CLIP_PLANE5                             = 0x3005;
+    public static final int GL_COLOR_ARRAY_BUFFER_BINDING              = 0x8898;
+    public static final int GL_COLOR_ARRAY_POINTER                     = 0x8090;
+    public static final int GL_COLOR_ARRAY_SIZE                        = 0x8081;
+    public static final int GL_COLOR_ARRAY_STRIDE                      = 0x8083;
+    public static final int GL_COLOR_ARRAY_TYPE                        = 0x8082;
+    public static final int GL_COLOR_CLEAR_VALUE                       = 0x0C22;
+    public static final int GL_COLOR_WRITEMASK                         = 0x0C23;
+    public static final int GL_COMBINE                                 = 0x8570;
+    public static final int GL_COMBINE_ALPHA                           = 0x8572;
+    public static final int GL_COMBINE_RGB                             = 0x8571;
+    public static final int GL_CONSTANT                                = 0x8576;
+    public static final int GL_COORD_REPLACE_OES                       = 0x8862;
+    public static final int GL_CULL_FACE_MODE                          = 0x0B45;
+    public static final int GL_CURRENT_COLOR                           = 0x0B00;
+    public static final int GL_CURRENT_NORMAL                          = 0x0B02;
+    public static final int GL_CURRENT_TEXTURE_COORDS                  = 0x0B03;
+    public static final int GL_DEPTH_CLEAR_VALUE                       = 0x0B73;
+    public static final int GL_DEPTH_FUNC                              = 0x0B74;
+    public static final int GL_DEPTH_RANGE                             = 0x0B70;
+    public static final int GL_DEPTH_WRITEMASK                         = 0x0B72;
+    public static final int GL_DOT3_RGB                                = 0x86AE;
+    public static final int GL_DOT3_RGBA                               = 0x86AF;
+    public static final int GL_DYNAMIC_DRAW                            = 0x88E8;
+    public static final int GL_ELEMENT_ARRAY_BUFFER                    = 0x8893;
+    public static final int GL_ELEMENT_ARRAY_BUFFER_BINDING            = 0x8895;
+    public static final int GL_FRONT_FACE                              = 0x0B46;
+    public static final int GL_GENERATE_MIPMAP                         = 0x8191;
+    public static final int GL_GENERATE_MIPMAP_HINT                    = 0x8192;
+    public static final int GL_INTERPOLATE                             = 0x8575;
+    public static final int GL_LINE_WIDTH                              = 0x0B21;
+    public static final int GL_LOGIC_OP_MODE                           = 0x0BF0;
+    public static final int GL_MATRIX_MODE                             = 0x0BA0;
+    public static final int GL_MAX_CLIP_PLANES                         = 0x0D32;
+    public static final int GL_MODELVIEW_MATRIX                        = 0x0BA6;
+    public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES  = 0x898D;
+    public static final int GL_MODELVIEW_STACK_DEPTH                   = 0x0BA3;
+    public static final int GL_NORMAL_ARRAY_BUFFER_BINDING             = 0x8897;
+    public static final int GL_NORMAL_ARRAY_POINTER                    = 0x808F;
+    public static final int GL_NORMAL_ARRAY_STRIDE                     = 0x807F;
+    public static final int GL_NORMAL_ARRAY_TYPE                       = 0x807E;
+    public static final int GL_OPERAND0_ALPHA                          = 0x8598;
+    public static final int GL_OPERAND0_RGB                            = 0x8590;
+    public static final int GL_OPERAND1_ALPHA                          = 0x8599;
+    public static final int GL_OPERAND1_RGB                            = 0x8591;
+    public static final int GL_OPERAND2_ALPHA                          = 0x859A;
+    public static final int GL_OPERAND2_RGB                            = 0x8592;
+    public static final int GL_POINT_DISTANCE_ATTENUATION              = 0x8129;
+    public static final int GL_POINT_FADE_THRESHOLD_SIZE               = 0x8128;
+    public static final int GL_POINT_SIZE                              = 0x0B11;
+    public static final int GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES     = 0x8B9F;
+    public static final int GL_POINT_SIZE_ARRAY_OES                    = 0x8B9C;
+    public static final int GL_POINT_SIZE_ARRAY_POINTER_OES            = 0x898C;
+    public static final int GL_POINT_SIZE_ARRAY_STRIDE_OES             = 0x898B;
+    public static final int GL_POINT_SIZE_ARRAY_TYPE_OES               = 0x898A;
+    public static final int GL_POINT_SIZE_MAX                          = 0x8127;
+    public static final int GL_POINT_SIZE_MIN                          = 0x8126;
+    public static final int GL_POINT_SPRITE_OES                        = 0x8861;
+    public static final int GL_POLYGON_OFFSET_FACTOR                   = 0x8038;
+    public static final int GL_POLYGON_OFFSET_UNITS                    = 0x2A00;
+    public static final int GL_PREVIOUS                                = 0x8578;
+    public static final int GL_PRIMARY_COLOR                           = 0x8577;
+    public static final int GL_PROJECTION_MATRIX                       = 0x0BA7;
+    public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES = 0x898E;
+    public static final int GL_PROJECTION_STACK_DEPTH                  = 0x0BA4;
+    public static final int GL_RGB_SCALE                               = 0x8573;
+    public static final int GL_SAMPLE_BUFFERS                          = 0x80A8;
+    public static final int GL_SAMPLE_COVERAGE_INVERT                  = 0x80AB;
+    public static final int GL_SAMPLE_COVERAGE_VALUE                   = 0x80AA;
+    public static final int GL_SAMPLES                                 = 0x80A9;
+    public static final int GL_SCISSOR_BOX                             = 0x0C10;
+    public static final int GL_SHADE_MODEL                             = 0x0B54;
+    public static final int GL_SRC0_ALPHA                              = 0x8588;
+    public static final int GL_SRC0_RGB                                = 0x8580;
+    public static final int GL_SRC1_ALPHA                              = 0x8589;
+    public static final int GL_SRC1_RGB                                = 0x8581;
+    public static final int GL_SRC2_ALPHA                              = 0x858A;
+    public static final int GL_SRC2_RGB                                = 0x8582;
+    public static final int GL_STATIC_DRAW                             = 0x88E4;
+    public static final int GL_STENCIL_CLEAR_VALUE                     = 0x0B91;
+    public static final int GL_STENCIL_FAIL                            = 0x0B94;
+    public static final int GL_STENCIL_FUNC                            = 0x0B92;
+    public static final int GL_STENCIL_PASS_DEPTH_FAIL                 = 0x0B95;
+    public static final int GL_STENCIL_PASS_DEPTH_PASS                 = 0x0B96;
+    public static final int GL_STENCIL_REF                             = 0x0B97;
+    public static final int GL_STENCIL_VALUE_MASK                      = 0x0B93;
+    public static final int GL_STENCIL_WRITEMASK                       = 0x0B98;
+    public static final int GL_SUBTRACT                                = 0x84E7;
+    public static final int GL_TEXTURE_BINDING_2D                      = 0x8069;
+    public static final int GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING      = 0x889A;
+    public static final int GL_TEXTURE_COORD_ARRAY_POINTER             = 0x8092;
+    public static final int GL_TEXTURE_COORD_ARRAY_SIZE                = 0x8088;
+    public static final int GL_TEXTURE_COORD_ARRAY_STRIDE              = 0x808A;
+    public static final int GL_TEXTURE_COORD_ARRAY_TYPE                = 0x8089;
+    public static final int GL_TEXTURE_MATRIX                          = 0x0BA8;
+    public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES    = 0x898F;
+    public static final int GL_TEXTURE_STACK_DEPTH                     = 0x0BA5;
+    public static final int GL_VERTEX_ARRAY_BUFFER_BINDING             = 0x8896;
+    public static final int GL_VERTEX_ARRAY_POINTER                    = 0x808E;
+    public static final int GL_VERTEX_ARRAY_SIZE                       = 0x807A;
+    public static final int GL_VERTEX_ARRAY_STRIDE                     = 0x807C;
+    public static final int GL_VERTEX_ARRAY_TYPE                       = 0x807B;
+    public static final int GL_VIEWPORT                                = 0x0BA2;
+    public static final int GL_WRITE_ONLY                              = 0x88B9;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+
+    // C function void glBindBuffer ( GLenum target, GLuint buffer )
+
+    public static native void glBindBuffer(
+        int target,
+        int buffer
+    );
+
+    // C function void glBufferData ( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage )
+
+    public static native void glBufferData(
+        int target,
+        int size,
+        java.nio.Buffer data,
+        int usage
+    );
+
+    // C function void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data )
+
+    public static native void glBufferSubData(
+        int target,
+        int offset,
+        int size,
+        java.nio.Buffer data
+    );
+
+    // C function void glClipPlanef ( GLenum plane, const GLfloat *equation )
+
+    public static native void glClipPlanef(
+        int plane,
+        float[] equation,
+        int offset
+    );
+
+    // C function void glClipPlanef ( GLenum plane, const GLfloat *equation )
+
+    public static native void glClipPlanef(
+        int plane,
+        java.nio.FloatBuffer equation
+    );
+
+    // C function void glClipPlanex ( GLenum plane, const GLfixed *equation )
+
+    public static native void glClipPlanex(
+        int plane,
+        int[] equation,
+        int offset
+    );
+
+    // C function void glClipPlanex ( GLenum plane, const GLfixed *equation )
+
+    public static native void glClipPlanex(
+        int plane,
+        java.nio.IntBuffer equation
+    );
+
+    // C function void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
+
+    public static native void glColor4ub(
+        byte red,
+        byte green,
+        byte blue,
+        byte alpha
+    );
+
+    // C function void glColorPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
+
+    public static native void glColorPointer(
+        int size,
+        int type,
+        int stride,
+        int offset
+    );
+
+    // C function void glDeleteBuffers ( GLsizei n, const GLuint *buffers )
+
+    public static native void glDeleteBuffers(
+        int n,
+        int[] buffers,
+        int offset
+    );
+
+    // C function void glDeleteBuffers ( GLsizei n, const GLuint *buffers )
+
+    public static native void glDeleteBuffers(
+        int n,
+        java.nio.IntBuffer buffers
+    );
+
+    // C function void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset )
+
+    public static native void glDrawElements(
+        int mode,
+        int count,
+        int type,
+        int offset
+    );
+
+    // C function void glGenBuffers ( GLsizei n, GLuint *buffers )
+
+    public static native void glGenBuffers(
+        int n,
+        int[] buffers,
+        int offset
+    );
+
+    // C function void glGenBuffers ( GLsizei n, GLuint *buffers )
+
+    public static native void glGenBuffers(
+        int n,
+        java.nio.IntBuffer buffers
+    );
+
+    // C function void glGetBooleanv ( GLenum pname, GLboolean *params )
+
+    public static native void glGetBooleanv(
+        int pname,
+        boolean[] params,
+        int offset
+    );
+
+    // C function void glGetBooleanv ( GLenum pname, GLboolean *params )
+
+    public static native void glGetBooleanv(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetBufferParameteriv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetBufferParameteriv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetClipPlanef ( GLenum pname, GLfloat *eqn )
+
+    public static native void glGetClipPlanef(
+        int pname,
+        float[] eqn,
+        int offset
+    );
+
+    // C function void glGetClipPlanef ( GLenum pname, GLfloat *eqn )
+
+    public static native void glGetClipPlanef(
+        int pname,
+        java.nio.FloatBuffer eqn
+    );
+
+    // C function void glGetClipPlanex ( GLenum pname, GLfixed *eqn )
+
+    public static native void glGetClipPlanex(
+        int pname,
+        int[] eqn,
+        int offset
+    );
+
+    // C function void glGetClipPlanex ( GLenum pname, GLfixed *eqn )
+
+    public static native void glGetClipPlanex(
+        int pname,
+        java.nio.IntBuffer eqn
+    );
+
+    // C function void glGetFixedv ( GLenum pname, GLfixed *params )
+
+    public static native void glGetFixedv(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetFixedv ( GLenum pname, GLfixed *params )
+
+    public static native void glGetFixedv(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetFloatv ( GLenum pname, GLfloat *params )
+
+    public static native void glGetFloatv(
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glGetFloatv ( GLenum pname, GLfloat *params )
+
+    public static native void glGetFloatv(
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params )
+
+    public static native void glGetLightfv(
+        int light,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params )
+
+    public static native void glGetLightfv(
+        int light,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params )
+
+    public static native void glGetLightxv(
+        int light,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params )
+
+    public static native void glGetLightxv(
+        int light,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params )
+
+    public static native void glGetMaterialfv(
+        int face,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params )
+
+    public static native void glGetMaterialfv(
+        int face,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params )
+
+    public static native void glGetMaterialxv(
+        int face,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params )
+
+    public static native void glGetMaterialxv(
+        int face,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexEnvfv(
+        int env,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexEnvfv(
+        int env,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params )
+
+    public static native void glGetTexEnviv(
+        int env,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params )
+
+    public static native void glGetTexEnviv(
+        int env,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexEnvxv(
+        int env,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexEnvxv(
+        int env,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexParameterfv(
+        int target,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexParameterfv(
+        int target,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetTexParameteriv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetTexParameteriv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexParameterxv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexParameterxv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function GLboolean glIsBuffer ( GLuint buffer )
+
+    public static native boolean glIsBuffer(
+        int buffer
+    );
+
+    // C function GLboolean glIsEnabled ( GLenum cap )
+
+    public static native boolean glIsEnabled(
+        int cap
+    );
+
+    // C function GLboolean glIsTexture ( GLuint texture )
+
+    public static native boolean glIsTexture(
+        int texture
+    );
+
+    // C function void glNormalPointer ( GLenum type, GLsizei stride, GLint offset )
+
+    public static native void glNormalPointer(
+        int type,
+        int stride,
+        int offset
+    );
+
+    // C function void glPointParameterf ( GLenum pname, GLfloat param )
+
+    public static native void glPointParameterf(
+        int pname,
+        float param
+    );
+
+    // C function void glPointParameterfv ( GLenum pname, const GLfloat *params )
+
+    public static native void glPointParameterfv(
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glPointParameterfv ( GLenum pname, const GLfloat *params )
+
+    public static native void glPointParameterfv(
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glPointParameterx ( GLenum pname, GLfixed param )
+
+    public static native void glPointParameterx(
+        int pname,
+        int param
+    );
+
+    // C function void glPointParameterxv ( GLenum pname, const GLfixed *params )
+
+    public static native void glPointParameterxv(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glPointParameterxv ( GLenum pname, const GLfixed *params )
+
+    public static native void glPointParameterxv(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer )
+
+    public static native void glPointSizePointerOES(
+        int type,
+        int stride,
+        java.nio.Buffer pointer
+    );
+
+    // C function void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
+
+    public static native void glTexCoordPointer(
+        int size,
+        int type,
+        int stride,
+        int offset
+    );
+
+    // C function void glTexEnvi ( GLenum target, GLenum pname, GLint param )
+
+    public static native void glTexEnvi(
+        int target,
+        int pname,
+        int param
+    );
+
+    // C function void glTexEnviv ( GLenum target, GLenum pname, const GLint *params )
+
+    public static native void glTexEnviv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexEnviv ( GLenum target, GLenum pname, const GLint *params )
+
+    public static native void glTexEnviv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params )
+
+    public static native void glTexParameterfv(
+        int target,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params )
+
+    public static native void glTexParameterfv(
+        int target,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glTexParameteri ( GLenum target, GLenum pname, GLint param )
+
+    public static native void glTexParameteri(
+        int target,
+        int pname,
+        int param
+    );
+
+    // C function void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params )
+
+    public static native void glTexParameteriv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params )
+
+    public static native void glTexParameteriv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexParameterxv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexParameterxv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
+
+    public static native void glVertexPointer(
+        int size,
+        int type,
+        int stride,
+        int offset
+    );
+
+}
diff --git a/opengl/java/android/opengl/GLES11Ext.java b/opengl/java/android/opengl/GLES11Ext.java
new file mode 100644
index 0000000..4384e9e
--- /dev/null
+++ b/opengl/java/android/opengl/GLES11Ext.java
@@ -0,0 +1,1076 @@
+/*
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+public class GLES11Ext {
+    public static final int GL_BLEND_EQUATION_RGB_OES                               = 0x8009;
+    public static final int GL_BLEND_EQUATION_ALPHA_OES                             = 0x883D;
+    public static final int GL_BLEND_DST_RGB_OES                                    = 0x80C8;
+    public static final int GL_BLEND_SRC_RGB_OES                                    = 0x80C9;
+    public static final int GL_BLEND_DST_ALPHA_OES                                  = 0x80CA;
+    public static final int GL_BLEND_SRC_ALPHA_OES                                  = 0x80CB;
+    public static final int GL_BLEND_EQUATION_OES                                   = 0x8009;
+    public static final int GL_FUNC_ADD_OES                                         = 0x8006;
+    public static final int GL_FUNC_SUBTRACT_OES                                    = 0x800A;
+    public static final int GL_FUNC_REVERSE_SUBTRACT_OES                            = 0x800B;
+    public static final int GL_ETC1_RGB8_OES                                        = 0x8D64;
+    public static final int GL_DEPTH_COMPONENT24_OES                                = 0x81A6;
+    public static final int GL_DEPTH_COMPONENT32_OES                                = 0x81A7;
+    public static final int GL_TEXTURE_CROP_RECT_OES                                = 0x8B9D;
+    public static final int GL_FIXED_OES                                            = 0x140C;
+    public static final int GL_NONE_OES                                             = 0;
+    public static final int GL_FRAMEBUFFER_OES                                      = 0x8D40;
+    public static final int GL_RENDERBUFFER_OES                                     = 0x8D41;
+    public static final int GL_RGBA4_OES                                            = 0x8056;
+    public static final int GL_RGB5_A1_OES                                          = 0x8057;
+    public static final int GL_RGB565_OES                                           = 0x8D62;
+    public static final int GL_DEPTH_COMPONENT16_OES                                = 0x81A5;
+    public static final int GL_RENDERBUFFER_WIDTH_OES                               = 0x8D42;
+    public static final int GL_RENDERBUFFER_HEIGHT_OES                              = 0x8D43;
+    public static final int GL_RENDERBUFFER_INTERNAL_FORMAT_OES                     = 0x8D44;
+    public static final int GL_RENDERBUFFER_RED_SIZE_OES                            = 0x8D50;
+    public static final int GL_RENDERBUFFER_GREEN_SIZE_OES                          = 0x8D51;
+    public static final int GL_RENDERBUFFER_BLUE_SIZE_OES                           = 0x8D52;
+    public static final int GL_RENDERBUFFER_ALPHA_SIZE_OES                          = 0x8D53;
+    public static final int GL_RENDERBUFFER_DEPTH_SIZE_OES                          = 0x8D54;
+    public static final int GL_RENDERBUFFER_STENCIL_SIZE_OES                        = 0x8D55;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES               = 0x8CD0;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES               = 0x8CD1;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES             = 0x8CD2;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES     = 0x8CD3;
+    public static final int GL_COLOR_ATTACHMENT0_OES                                = 0x8CE0;
+    public static final int GL_DEPTH_ATTACHMENT_OES                                 = 0x8D00;
+    public static final int GL_STENCIL_ATTACHMENT_OES                               = 0x8D20;
+    public static final int GL_FRAMEBUFFER_COMPLETE_OES                             = 0x8CD5;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES                = 0x8CD6;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES        = 0x8CD7;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES                = 0x8CD9;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES                   = 0x8CDA;
+    public static final int GL_FRAMEBUFFER_UNSUPPORTED_OES                          = 0x8CDD;
+    public static final int GL_FRAMEBUFFER_BINDING_OES                              = 0x8CA6;
+    public static final int GL_RENDERBUFFER_BINDING_OES                             = 0x8CA7;
+    public static final int GL_MAX_RENDERBUFFER_SIZE_OES                            = 0x84E8;
+    public static final int GL_INVALID_FRAMEBUFFER_OPERATION_OES                    = 0x0506;
+    public static final int GL_WRITE_ONLY_OES                                       = 0x88B9;
+    public static final int GL_BUFFER_ACCESS_OES                                    = 0x88BB;
+    public static final int GL_BUFFER_MAPPED_OES                                    = 0x88BC;
+    public static final int GL_BUFFER_MAP_POINTER_OES                               = 0x88BD;
+    public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES               = 0x898D;
+    public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES              = 0x898E;
+    public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES                 = 0x898F;
+    public static final int GL_MAX_VERTEX_UNITS_OES                                 = 0x86A4;
+    public static final int GL_MAX_PALETTE_MATRICES_OES                             = 0x8842;
+    public static final int GL_MATRIX_PALETTE_OES                                   = 0x8840;
+    public static final int GL_MATRIX_INDEX_ARRAY_OES                               = 0x8844;
+    public static final int GL_WEIGHT_ARRAY_OES                                     = 0x86AD;
+    public static final int GL_CURRENT_PALETTE_MATRIX_OES                           = 0x8843;
+    public static final int GL_MATRIX_INDEX_ARRAY_SIZE_OES                          = 0x8846;
+    public static final int GL_MATRIX_INDEX_ARRAY_TYPE_OES                          = 0x8847;
+    public static final int GL_MATRIX_INDEX_ARRAY_STRIDE_OES                        = 0x8848;
+    public static final int GL_MATRIX_INDEX_ARRAY_POINTER_OES                       = 0x8849;
+    public static final int GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES                = 0x8B9E;
+    public static final int GL_WEIGHT_ARRAY_SIZE_OES                                = 0x86AB;
+    public static final int GL_WEIGHT_ARRAY_TYPE_OES                                = 0x86A9;
+    public static final int GL_WEIGHT_ARRAY_STRIDE_OES                              = 0x86AA;
+    public static final int GL_WEIGHT_ARRAY_POINTER_OES                             = 0x86AC;
+    public static final int GL_WEIGHT_ARRAY_BUFFER_BINDING_OES                      = 0x889E;
+    public static final int GL_DEPTH_STENCIL_OES                                    = 0x84F9;
+    public static final int GL_UNSIGNED_INT_24_8_OES                                = 0x84FA;
+    public static final int GL_DEPTH24_STENCIL8_OES                                 = 0x88F0;
+    public static final int GL_RGB8_OES                                             = 0x8051;
+    public static final int GL_RGBA8_OES                                            = 0x8058;
+    public static final int GL_STENCIL_INDEX1_OES                                   = 0x8D46;
+    public static final int GL_STENCIL_INDEX4_OES                                   = 0x8D47;
+    public static final int GL_STENCIL_INDEX8_OES                                   = 0x8D48;
+    public static final int GL_INCR_WRAP_OES                                        = 0x8507;
+    public static final int GL_DECR_WRAP_OES                                        = 0x8508;
+    public static final int GL_NORMAL_MAP_OES                                       = 0x8511;
+    public static final int GL_REFLECTION_MAP_OES                                   = 0x8512;
+    public static final int GL_TEXTURE_CUBE_MAP_OES                                 = 0x8513;
+    public static final int GL_TEXTURE_BINDING_CUBE_MAP_OES                         = 0x8514;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES                      = 0x8515;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES                      = 0x8516;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES                      = 0x8517;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES                      = 0x8518;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES                      = 0x8519;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES                      = 0x851A;
+    public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES                        = 0x851C;
+    public static final int GL_TEXTURE_GEN_MODE_OES                                 = 0x2500;
+    public static final int GL_TEXTURE_GEN_STR_OES                                  = 0x8D60;
+    public static final int GL_MIRRORED_REPEAT_OES                                  = 0x8370;
+    public static final int GL_3DC_X_AMD                                            = 0x87F9;
+    public static final int GL_3DC_XY_AMD                                           = 0x87FA;
+    public static final int GL_ATC_RGB_AMD                                          = 0x8C92;
+    public static final int GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          = 0x8C93;
+    public static final int GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      = 0x87EE;
+    public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT                           = 0x84FE;
+    public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       = 0x84FF;
+    public static final int GL_BGRA                                                 = 0x80E1;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+    
+    // C function void glBlendEquationSeparateOES ( GLenum modeRGB, GLenum modeAlpha )
+
+    public static native void glBlendEquationSeparateOES(
+        int modeRGB,
+        int modeAlpha
+    );
+
+    // C function void glBlendFuncSeparateOES ( GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha )
+
+    public static native void glBlendFuncSeparateOES(
+        int srcRGB,
+        int dstRGB,
+        int srcAlpha,
+        int dstAlpha
+    );
+
+    // C function void glBlendEquationOES ( GLenum mode )
+
+    public static native void glBlendEquationOES(
+        int mode
+    );
+
+    // C function void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height )
+
+    public static native void glDrawTexsOES(
+        short x,
+        short y,
+        short z,
+        short width,
+        short height
+    );
+
+    // C function void glDrawTexiOES ( GLint x, GLint y, GLint z, GLint width, GLint height )
+
+    public static native void glDrawTexiOES(
+        int x,
+        int y,
+        int z,
+        int width,
+        int height
+    );
+
+    // C function void glDrawTexxOES ( GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height )
+
+    public static native void glDrawTexxOES(
+        int x,
+        int y,
+        int z,
+        int width,
+        int height
+    );
+
+    // C function void glDrawTexsvOES ( const GLshort *coords )
+
+    public static native void glDrawTexsvOES(
+        short[] coords,
+        int offset
+    );
+
+    // C function void glDrawTexsvOES ( const GLshort *coords )
+
+    public static native void glDrawTexsvOES(
+        java.nio.ShortBuffer coords
+    );
+
+    // C function void glDrawTexivOES ( const GLint *coords )
+
+    public static native void glDrawTexivOES(
+        int[] coords,
+        int offset
+    );
+
+    // C function void glDrawTexivOES ( const GLint *coords )
+
+    public static native void glDrawTexivOES(
+        java.nio.IntBuffer coords
+    );
+
+    // C function void glDrawTexxvOES ( const GLfixed *coords )
+
+    public static native void glDrawTexxvOES(
+        int[] coords,
+        int offset
+    );
+
+    // C function void glDrawTexxvOES ( const GLfixed *coords )
+
+    public static native void glDrawTexxvOES(
+        java.nio.IntBuffer coords
+    );
+
+    // C function void glDrawTexfOES ( GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height )
+
+    public static native void glDrawTexfOES(
+        float x,
+        float y,
+        float z,
+        float width,
+        float height
+    );
+
+    // C function void glDrawTexfvOES ( const GLfloat *coords )
+
+    public static native void glDrawTexfvOES(
+        float[] coords,
+        int offset
+    );
+
+    // C function void glDrawTexfvOES ( const GLfloat *coords )
+
+    public static native void glDrawTexfvOES(
+        java.nio.FloatBuffer coords
+    );
+
+    // C function void glEGLImageTargetTexture2DOES ( GLenum target, GLeglImageOES image )
+
+    public static native void glEGLImageTargetTexture2DOES(
+        int target,
+        java.nio.Buffer image
+    );
+
+    // C function void glEGLImageTargetRenderbufferStorageOES ( GLenum target, GLeglImageOES image )
+
+    public static native void glEGLImageTargetRenderbufferStorageOES(
+        int target,
+        java.nio.Buffer image
+    );
+
+    // C function void glAlphaFuncxOES ( GLenum func, GLclampx ref )
+
+    public static native void glAlphaFuncxOES(
+        int func,
+        int ref
+    );
+
+    // C function void glClearColorxOES ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha )
+
+    public static native void glClearColorxOES(
+        int red,
+        int green,
+        int blue,
+        int alpha
+    );
+
+    // C function void glClearDepthxOES ( GLclampx depth )
+
+    public static native void glClearDepthxOES(
+        int depth
+    );
+
+    // C function void glClipPlanexOES ( GLenum plane, const GLfixed *equation )
+
+    public static native void glClipPlanexOES(
+        int plane,
+        int[] equation,
+        int offset
+    );
+
+    // C function void glClipPlanexOES ( GLenum plane, const GLfixed *equation )
+
+    public static native void glClipPlanexOES(
+        int plane,
+        java.nio.IntBuffer equation
+    );
+
+    // C function void glColor4xOES ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha )
+
+    public static native void glColor4xOES(
+        int red,
+        int green,
+        int blue,
+        int alpha
+    );
+
+    // C function void glDepthRangexOES ( GLclampx zNear, GLclampx zFar )
+
+    public static native void glDepthRangexOES(
+        int zNear,
+        int zFar
+    );
+
+    // C function void glFogxOES ( GLenum pname, GLfixed param )
+
+    public static native void glFogxOES(
+        int pname,
+        int param
+    );
+
+    // C function void glFogxvOES ( GLenum pname, const GLfixed *params )
+
+    public static native void glFogxvOES(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glFogxvOES ( GLenum pname, const GLfixed *params )
+
+    public static native void glFogxvOES(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glFrustumxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+
+    public static native void glFrustumxOES(
+        int left,
+        int right,
+        int bottom,
+        int top,
+        int zNear,
+        int zFar
+    );
+
+    // C function void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn )
+
+    public static native void glGetClipPlanexOES(
+        int pname,
+        int[] eqn,
+        int offset
+    );
+
+    // C function void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn )
+
+    public static native void glGetClipPlanexOES(
+        int pname,
+        java.nio.IntBuffer eqn
+    );
+
+    // C function void glGetFixedvOES ( GLenum pname, GLfixed *params )
+
+    public static native void glGetFixedvOES(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetFixedvOES ( GLenum pname, GLfixed *params )
+
+    public static native void glGetFixedvOES(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params )
+
+    public static native void glGetLightxvOES(
+        int light,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params )
+
+    public static native void glGetLightxvOES(
+        int light,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params )
+
+    public static native void glGetMaterialxvOES(
+        int face,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params )
+
+    public static native void glGetMaterialxvOES(
+        int face,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexEnvxvOES(
+        int env,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexEnvxvOES(
+        int env,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexParameterxvOES(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexParameterxvOES(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glLightModelxOES ( GLenum pname, GLfixed param )
+
+    public static native void glLightModelxOES(
+        int pname,
+        int param
+    );
+
+    // C function void glLightModelxvOES ( GLenum pname, const GLfixed *params )
+
+    public static native void glLightModelxvOES(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glLightModelxvOES ( GLenum pname, const GLfixed *params )
+
+    public static native void glLightModelxvOES(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glLightxOES ( GLenum light, GLenum pname, GLfixed param )
+
+    public static native void glLightxOES(
+        int light,
+        int pname,
+        int param
+    );
+
+    // C function void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params )
+
+    public static native void glLightxvOES(
+        int light,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params )
+
+    public static native void glLightxvOES(
+        int light,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glLineWidthxOES ( GLfixed width )
+
+    public static native void glLineWidthxOES(
+        int width
+    );
+
+    // C function void glLoadMatrixxOES ( const GLfixed *m )
+
+    public static native void glLoadMatrixxOES(
+        int[] m,
+        int offset
+    );
+
+    // C function void glLoadMatrixxOES ( const GLfixed *m )
+
+    public static native void glLoadMatrixxOES(
+        java.nio.IntBuffer m
+    );
+
+    // C function void glMaterialxOES ( GLenum face, GLenum pname, GLfixed param )
+
+    public static native void glMaterialxOES(
+        int face,
+        int pname,
+        int param
+    );
+
+    // C function void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params )
+
+    public static native void glMaterialxvOES(
+        int face,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params )
+
+    public static native void glMaterialxvOES(
+        int face,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glMultMatrixxOES ( const GLfixed *m )
+
+    public static native void glMultMatrixxOES(
+        int[] m,
+        int offset
+    );
+
+    // C function void glMultMatrixxOES ( const GLfixed *m )
+
+    public static native void glMultMatrixxOES(
+        java.nio.IntBuffer m
+    );
+
+    // C function void glMultiTexCoord4xOES ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q )
+
+    public static native void glMultiTexCoord4xOES(
+        int target,
+        int s,
+        int t,
+        int r,
+        int q
+    );
+
+    // C function void glNormal3xOES ( GLfixed nx, GLfixed ny, GLfixed nz )
+
+    public static native void glNormal3xOES(
+        int nx,
+        int ny,
+        int nz
+    );
+
+    // C function void glOrthoxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+
+    public static native void glOrthoxOES(
+        int left,
+        int right,
+        int bottom,
+        int top,
+        int zNear,
+        int zFar
+    );
+
+    // C function void glPointParameterxOES ( GLenum pname, GLfixed param )
+
+    public static native void glPointParameterxOES(
+        int pname,
+        int param
+    );
+
+    // C function void glPointParameterxvOES ( GLenum pname, const GLfixed *params )
+
+    public static native void glPointParameterxvOES(
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glPointParameterxvOES ( GLenum pname, const GLfixed *params )
+
+    public static native void glPointParameterxvOES(
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glPointSizexOES ( GLfixed size )
+
+    public static native void glPointSizexOES(
+        int size
+    );
+
+    // C function void glPolygonOffsetxOES ( GLfixed factor, GLfixed units )
+
+    public static native void glPolygonOffsetxOES(
+        int factor,
+        int units
+    );
+
+    // C function void glRotatexOES ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z )
+
+    public static native void glRotatexOES(
+        int angle,
+        int x,
+        int y,
+        int z
+    );
+
+    // C function void glSampleCoveragexOES ( GLclampx value, GLboolean invert )
+
+    public static native void glSampleCoveragexOES(
+        int value,
+        boolean invert
+    );
+
+    // C function void glScalexOES ( GLfixed x, GLfixed y, GLfixed z )
+
+    public static native void glScalexOES(
+        int x,
+        int y,
+        int z
+    );
+
+    // C function void glTexEnvxOES ( GLenum target, GLenum pname, GLfixed param )
+
+    public static native void glTexEnvxOES(
+        int target,
+        int pname,
+        int param
+    );
+
+    // C function void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexEnvxvOES(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexEnvxvOES(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTexParameterxOES ( GLenum target, GLenum pname, GLfixed param )
+
+    public static native void glTexParameterxOES(
+        int target,
+        int pname,
+        int param
+    );
+
+    // C function void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexParameterxvOES(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+
+    public static native void glTexParameterxvOES(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTranslatexOES ( GLfixed x, GLfixed y, GLfixed z )
+
+    public static native void glTranslatexOES(
+        int x,
+        int y,
+        int z
+    );
+
+    // C function GLboolean glIsRenderbufferOES ( GLuint renderbuffer )
+
+    public static native boolean glIsRenderbufferOES(
+        int renderbuffer
+    );
+
+    // C function void glBindRenderbufferOES ( GLenum target, GLuint renderbuffer )
+
+    public static native void glBindRenderbufferOES(
+        int target,
+        int renderbuffer
+    );
+
+    // C function void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers )
+
+    public static native void glDeleteRenderbuffersOES(
+        int n,
+        int[] renderbuffers,
+        int offset
+    );
+
+    // C function void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers )
+
+    public static native void glDeleteRenderbuffersOES(
+        int n,
+        java.nio.IntBuffer renderbuffers
+    );
+
+    // C function void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers )
+
+    public static native void glGenRenderbuffersOES(
+        int n,
+        int[] renderbuffers,
+        int offset
+    );
+
+    // C function void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers )
+
+    public static native void glGenRenderbuffersOES(
+        int n,
+        java.nio.IntBuffer renderbuffers
+    );
+
+    // C function void glRenderbufferStorageOES ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height )
+
+    public static native void glRenderbufferStorageOES(
+        int target,
+        int internalformat,
+        int width,
+        int height
+    );
+
+    // C function void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetRenderbufferParameterivOES(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetRenderbufferParameterivOES(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function GLboolean glIsFramebufferOES ( GLuint framebuffer )
+
+    public static native boolean glIsFramebufferOES(
+        int framebuffer
+    );
+
+    // C function void glBindFramebufferOES ( GLenum target, GLuint framebuffer )
+
+    public static native void glBindFramebufferOES(
+        int target,
+        int framebuffer
+    );
+
+    // C function void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers )
+
+    public static native void glDeleteFramebuffersOES(
+        int n,
+        int[] framebuffers,
+        int offset
+    );
+
+    // C function void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers )
+
+    public static native void glDeleteFramebuffersOES(
+        int n,
+        java.nio.IntBuffer framebuffers
+    );
+
+    // C function void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers )
+
+    public static native void glGenFramebuffersOES(
+        int n,
+        int[] framebuffers,
+        int offset
+    );
+
+    // C function void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers )
+
+    public static native void glGenFramebuffersOES(
+        int n,
+        java.nio.IntBuffer framebuffers
+    );
+
+    // C function GLenum glCheckFramebufferStatusOES ( GLenum target )
+
+    public static native int glCheckFramebufferStatusOES(
+        int target
+    );
+
+    // C function void glFramebufferRenderbufferOES ( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer )
+
+    public static native void glFramebufferRenderbufferOES(
+        int target,
+        int attachment,
+        int renderbuffertarget,
+        int renderbuffer
+    );
+
+    // C function void glFramebufferTexture2DOES ( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level )
+
+    public static native void glFramebufferTexture2DOES(
+        int target,
+        int attachment,
+        int textarget,
+        int texture,
+        int level
+    );
+
+    // C function void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params )
+
+    public static native void glGetFramebufferAttachmentParameterivOES(
+        int target,
+        int attachment,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params )
+
+    public static native void glGetFramebufferAttachmentParameterivOES(
+        int target,
+        int attachment,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGenerateMipmapOES ( GLenum target )
+
+    public static native void glGenerateMipmapOES(
+        int target
+    );
+
+    // C function void glCurrentPaletteMatrixOES ( GLuint matrixpaletteindex )
+
+    public static native void glCurrentPaletteMatrixOES(
+        int matrixpaletteindex
+    );
+
+    // C function void glLoadPaletteFromModelViewMatrixOES ( void )
+
+    public static native void glLoadPaletteFromModelViewMatrixOES(
+    );
+
+    // C function void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+
+    public static native void glMatrixIndexPointerOES(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer
+    );
+
+    // C function void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+
+    public static native void glWeightPointerOES(
+        int size,
+        int type,
+        int stride,
+        java.nio.Buffer pointer
+    );
+
+    // C function void glDepthRangefOES ( GLclampf zNear, GLclampf zFar )
+
+    public static native void glDepthRangefOES(
+        float zNear,
+        float zFar
+    );
+
+    // C function void glFrustumfOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+
+    public static native void glFrustumfOES(
+        float left,
+        float right,
+        float bottom,
+        float top,
+        float zNear,
+        float zFar
+    );
+
+    // C function void glOrthofOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+
+    public static native void glOrthofOES(
+        float left,
+        float right,
+        float bottom,
+        float top,
+        float zNear,
+        float zFar
+    );
+
+    // C function void glClipPlanefOES ( GLenum plane, const GLfloat *equation )
+
+    public static native void glClipPlanefOES(
+        int plane,
+        float[] equation,
+        int offset
+    );
+
+    // C function void glClipPlanefOES ( GLenum plane, const GLfloat *equation )
+
+    public static native void glClipPlanefOES(
+        int plane,
+        java.nio.FloatBuffer equation
+    );
+
+    // C function void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn )
+
+    public static native void glGetClipPlanefOES(
+        int pname,
+        float[] eqn,
+        int offset
+    );
+
+    // C function void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn )
+
+    public static native void glGetClipPlanefOES(
+        int pname,
+        java.nio.FloatBuffer eqn
+    );
+
+    // C function void glClearDepthfOES ( GLclampf depth )
+
+    public static native void glClearDepthfOES(
+        float depth
+    );
+
+    // C function void glTexGenfOES ( GLenum coord, GLenum pname, GLfloat param )
+
+    public static native void glTexGenfOES(
+        int coord,
+        int pname,
+        float param
+    );
+
+    // C function void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params )
+
+    public static native void glTexGenfvOES(
+        int coord,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params )
+
+    public static native void glTexGenfvOES(
+        int coord,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glTexGeniOES ( GLenum coord, GLenum pname, GLint param )
+
+    public static native void glTexGeniOES(
+        int coord,
+        int pname,
+        int param
+    );
+
+    // C function void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params )
+
+    public static native void glTexGenivOES(
+        int coord,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params )
+
+    public static native void glTexGenivOES(
+        int coord,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTexGenxOES ( GLenum coord, GLenum pname, GLfixed param )
+
+    public static native void glTexGenxOES(
+        int coord,
+        int pname,
+        int param
+    );
+
+    // C function void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params )
+
+    public static native void glTexGenxvOES(
+        int coord,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params )
+
+    public static native void glTexGenxvOES(
+        int coord,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexGenfvOES(
+        int coord,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexGenfvOES(
+        int coord,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params )
+
+    public static native void glGetTexGenivOES(
+        int coord,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params )
+
+    public static native void glGetTexGenivOES(
+        int coord,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexGenxvOES(
+        int coord,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params )
+
+    public static native void glGetTexGenxvOES(
+        int coord,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+}
diff --git a/opengl/java/android/opengl/GLU.java b/opengl/java/android/opengl/GLU.java
index 0152f42..49a43d0 100644
--- a/opengl/java/android/opengl/GLU.java
+++ b/opengl/java/android/opengl/GLU.java
@@ -20,14 +20,14 @@
 
 /**
  * A set of GL utilities inspired by the OpenGL Utility Toolkit.
- * 
+ *
  */
 
 public class GLU {
 
     /**
      * Return an error string from a GL or GLU error code.
-     * 
+     *
      * @param error - a GL or GLU error code.
      * @return the error string for the input error code, or NULL if the input
      *         was not a valid GL or GLU error code.
@@ -56,7 +56,7 @@
     /**
      * Define a viewing transformation in terms of an eye point, a center of
      * view, and an up vector.
-     * 
+     *
      * @param gl a GL10 interface
      * @param eyeX eye point X
      * @param eyeY eye point Y
@@ -89,46 +89,48 @@
         float sx = fy * upZ - fz * upY;
         float sy = fz * upX - fx * upZ;
         float sz = fx * upY - fy * upX;
-        
+
         // and normalize s
         float rls = 1.0f / Matrix.length(sx, sy, sz);
         sx *= rls;
         sy *= rls;
         sz *= rls;
-        
+
         // compute u = s x f
         float ux = sy * fz - sz * fy;
         float uy = sz * fx - sx * fz;
         float uz = sx * fy - sy * fx;
 
-        float[] m = new float[16];
-        m[0] = sx;
-        m[1] = ux;
-        m[2] = -fx;
-        m[3] = 0.0f;
+        float[] scratch = sScratch;
+        synchronized(scratch) {
+            scratch[0] = sx;
+            scratch[1] = ux;
+            scratch[2] = -fx;
+            scratch[3] = 0.0f;
 
-        m[4] = sy;
-        m[5] = uy;
-        m[6] = -fy;
-        m[7] = 0.0f;
+            scratch[4] = sy;
+            scratch[5] = uy;
+            scratch[6] = -fy;
+            scratch[7] = 0.0f;
 
-        m[8] = sz;
-        m[9] = uz;
-        m[10] = -fz;
-        m[11] = 0.0f;
+            scratch[8] = sz;
+            scratch[9] = uz;
+            scratch[10] = -fz;
+            scratch[11] = 0.0f;
 
-        m[12] = 0.0f;
-        m[13] = 0.0f;
-        m[14] = 0.0f;
-        m[15] = 1.0f;
+            scratch[12] = 0.0f;
+            scratch[13] = 0.0f;
+            scratch[14] = 0.0f;
+            scratch[15] = 1.0f;
 
-        gl.glMultMatrixf(m, 0);
+            gl.glMultMatrixf(scratch, 0);
+        }
         gl.glTranslatef(-eyeX, -eyeY, -eyeZ);
     }
 
     /**
      * Set up a 2D orthographic projection matrix
-     * 
+     *
      * @param gl
      * @param left
      * @param right
@@ -142,7 +144,7 @@
 
     /**
      * Set up a perspective projection matrix
-     * 
+     *
      * @param gl a GL10 interface
      * @param fovy specifies the field of view angle, in degrees, in the Y
      *        direction.
@@ -170,7 +172,7 @@
      * <p>
      * Note that you can use the OES_matrix_get extension, if present, to get
      * the current modelView and projection matrices.
-     * 
+     *
      * @param objX object coordinates X
      * @param objY object coordinates Y
      * @param objZ object coordinates Z
@@ -193,35 +195,39 @@
     public static int gluProject(float objX, float objY, float objZ,
             float[] model, int modelOffset, float[] project, int projectOffset,
             int[] view, int viewOffset, float[] win, int winOffset) {
-        float[] m = new float[16];
-        Matrix.multiplyMM(m, 0, project, projectOffset, model, modelOffset);
+        float[] scratch = sScratch;
+        synchronized(scratch) {
+            final int M_OFFSET = 0; // 0..15
+            final int V_OFFSET = 16; // 16..19
+            final int V2_OFFSET = 20; // 20..23
+            Matrix.multiplyMM(scratch, M_OFFSET, project, projectOffset,
+                    model, modelOffset);
 
-        float[] v = new float[4];
+            scratch[V_OFFSET + 0] = objX;
+            scratch[V_OFFSET + 1] = objY;
+            scratch[V_OFFSET + 2] = objZ;
+            scratch[V_OFFSET + 3] = 1.0f;
 
-        v[0] = objX;
-        v[1] = objY;
-        v[2] = objZ;
-        v[3] = 1.0f;
+            Matrix.multiplyMV(scratch, V2_OFFSET,
+                    scratch, M_OFFSET, scratch, V_OFFSET);
 
-        float[] v2 = new float[4];
+            float w = scratch[V2_OFFSET + 3];
+            if (w == 0.0f) {
+                return GL10.GL_FALSE;
+            }
 
-        Matrix.multiplyMV(v2, 0, m, 0, v, 0);
+            float rw = 1.0f / w;
 
-        float w = v2[3];
-        if (w == 0.0f) {
-            return GL10.GL_FALSE;
+            win[winOffset] =
+                    view[viewOffset] + view[viewOffset + 2]
+                            * (scratch[V2_OFFSET + 0] * rw + 1.0f)
+                            * 0.5f;
+            win[winOffset + 1] =
+                    view[viewOffset + 1] + view[viewOffset + 3]
+                            * (scratch[V2_OFFSET + 1] * rw + 1.0f) * 0.5f;
+            win[winOffset + 2] = (scratch[V2_OFFSET + 2] * rw + 1.0f) * 0.5f;
         }
 
-        float rw = 1.0f / w;
-
-        win[winOffset] =
-                view[viewOffset] + view[viewOffset + 2] * (v2[0] * rw + 1.0f)
-                        * 0.5f;
-        win[winOffset + 1] =
-                view[viewOffset + 1] + view[viewOffset + 3]
-                        * (v2[1] * rw + 1.0f) * 0.5f;
-        win[winOffset + 2] = (v2[2] * rw + 1.0f) * 0.5f;
-
         return GL10.GL_TRUE;
     }
 
@@ -232,7 +238,7 @@
      * <p>
      * Note that you can use the OES_matrix_get extension, if present, to get
      * the current modelView and projection matrices.
-     * 
+     *
      * @param winX window coordinates X
      * @param winY window coordinates Y
      * @param winZ window coordinates Z
@@ -255,34 +261,33 @@
     public static int gluUnProject(float winX, float winY, float winZ,
             float[] model, int modelOffset, float[] project, int projectOffset,
             int[] view, int viewOffset, float[] obj, int objOffset) {
-        float[] pm = new float[16];
-        Matrix.multiplyMM(pm, 0, project, projectOffset, model, modelOffset);
+        float[] scratch = sScratch;
+        synchronized(scratch) {
+            final int PM_OFFSET = 0; // 0..15
+            final int INVPM_OFFSET = 16; // 16..31
+               final int V_OFFSET = 0; // 0..3 Reuses PM_OFFSET space
+            Matrix.multiplyMM(scratch, PM_OFFSET, project, projectOffset,
+                    model, modelOffset);
 
-        float[] invPM = new float[16];
-        if (!Matrix.invertM(invPM, 0, pm, 0)) {
-            return GL10.GL_FALSE;
+            if (!Matrix.invertM(scratch, INVPM_OFFSET, scratch, PM_OFFSET)) {
+                return GL10.GL_FALSE;
+            }
+
+            scratch[V_OFFSET + 0] =
+                    2.0f * (winX - view[viewOffset + 0]) / view[viewOffset + 2]
+                            - 1.0f;
+            scratch[V_OFFSET + 1] =
+                    2.0f * (winY - view[viewOffset + 1]) / view[viewOffset + 3]
+                            - 1.0f;
+            scratch[V_OFFSET + 2] = 2.0f * winZ - 1.0f;
+            scratch[V_OFFSET + 3] = 1.0f;
+
+            Matrix.multiplyMV(obj, objOffset, scratch, INVPM_OFFSET,
+                    scratch, V_OFFSET);
         }
 
-        float[] v = new float[4];
-
-        v[0] =
-                2.0f * (winX - view[viewOffset + 0]) / view[viewOffset + 2]
-                        - 1.0f;
-        v[1] =
-                2.0f * (winY - view[viewOffset + 1]) / view[viewOffset + 3]
-                        - 1.0f;
-        v[2] = 2.0f * winZ - 1.0f;
-        v[3] = 1.0f;
-
-        float[] v2 = new float[4];
-
-        Matrix.multiplyMV(v2, 0, invPM, 0, v, 0);
-
-        obj[objOffset] = v2[0];
-        obj[objOffset + 1] = v2[1];
-        obj[objOffset + 2] = v2[2];
-
         return GL10.GL_TRUE;
     }
 
+    private static final float[] sScratch = new float[32];
  }
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 3b4c041..c44478d 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -1,17 +1,17 @@
-/* 
+/*
 **
 ** Copyright 2007 The Android Open Source Project
 **
-** Licensed under the Apache License Version 2.0(the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License Version 2.0(the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing software 
-** distributed under the License is distributed on an "AS IS" BASIS 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing software
+** distributed under the License is distributed on an "AS IS" BASIS
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
@@ -478,22 +478,38 @@
 };
 
 static const extention_map_t gExtentionMap[] = {
-    { "glDrawTexsOES",              (void(*)())&glDrawTexsOES },
-    { "glDrawTexiOES",              (void(*)())&glDrawTexiOES },
-    { "glDrawTexfOES",              (void(*)())&glDrawTexfOES },
-    { "glDrawTexxOES",              (void(*)())&glDrawTexxOES },
-    { "glDrawTexsvOES",             (void(*)())&glDrawTexsvOES },
-    { "glDrawTexivOES",             (void(*)())&glDrawTexivOES },
-    { "glDrawTexfvOES",             (void(*)())&glDrawTexfvOES },
-    { "glDrawTexxvOES",             (void(*)())&glDrawTexxvOES },
-    { "glQueryMatrixxOES",          (void(*)())&glQueryMatrixxOES },
-    { "glClipPlanef",               (void(*)())&glClipPlanef },
-    { "glClipPlanex",               (void(*)())&glClipPlanex },
-    { "glBindBuffer",               (void(*)())&glBindBuffer },
-    { "glBufferData",               (void(*)())&glBufferData },
-    { "glBufferSubData",            (void(*)())&glBufferSubData },
-    { "glDeleteBuffers",            (void(*)())&glDeleteBuffers },
-    { "glGenBuffers",               (void(*)())&glGenBuffers },
+    { "glDrawTexsOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES },
+    { "glDrawTexiOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES },
+    { "glDrawTexfOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES },
+    { "glDrawTexxOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES },
+    { "glDrawTexsvOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES },
+    { "glDrawTexivOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES },
+    { "glDrawTexfvOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES },
+    { "glDrawTexxvOES",
+            (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES },
+    { "glQueryMatrixxOES",
+            (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES },
+    { "glClipPlanef",
+            (__eglMustCastToProperFunctionPointerType)&glClipPlanef },
+    { "glClipPlanex",
+            (__eglMustCastToProperFunctionPointerType)&glClipPlanex },
+    { "glBindBuffer",
+            (__eglMustCastToProperFunctionPointerType)&glBindBuffer },
+    { "glBufferData",
+            (__eglMustCastToProperFunctionPointerType)&glBufferData },
+    { "glBufferSubData",
+            (__eglMustCastToProperFunctionPointerType)&glBufferSubData },
+    { "glDeleteBuffers",
+            (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers },
+    { "glGenBuffers",
+            (__eglMustCastToProperFunctionPointerType)&glGenBuffers },
 };
 
 /* 
@@ -1299,6 +1315,8 @@
         }
     }
 
+    // TODO: call connect / disconnect on the surface
+
     ogles_context_t* gl = (ogles_context_t*)ctx;
     if (makeCurrent(gl) == 0) {
         if (ctx) {
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 2ecc7768..d636d73 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -35,7 +35,6 @@
 
 LOCAL_SRC_FILES:= 	\
 	GLES_CM/gl.cpp.arm 		\
-	GLES_CM/gl_logger.cpp 	\
 #
 
 LOCAL_SHARED_LIBRARIES += libcutils libutils libui libEGL
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 0b4bcce..5ed3ecc 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -14,7 +14,7 @@
  ** limitations under the License.
  */
 
-#define LOG_TAG "GLLogger"
+#define LOG_TAG "libEGL"
 
 #include <ctype.h>
 #include <string.h>
@@ -69,9 +69,9 @@
 
 struct egl_display_t : public egl_object_t<'_dpy'>
 {
-    EGLDisplay  dpys[2];
-    EGLConfig*  configs[2];
-    EGLint      numConfigs[2];
+    EGLDisplay  dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+    EGLConfig*  configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
+    EGLint      numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
     EGLint      numTotalConfigs;
     char const* extensionsString;
     volatile int32_t refs;
@@ -81,7 +81,7 @@
         char const * clientApi;
         char const * extensions;
     };
-    strings_t   queryString[2];
+    strings_t   queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
 };
 
 struct egl_surface_t : public egl_object_t<'_srf'>
@@ -143,6 +143,7 @@
 
 static char const * const gl_names[] = {
     #include "gl_entries.in"
+    #include "glext_entries.in"
     NULL
 };
 
@@ -156,7 +157,7 @@
 
 // ----------------------------------------------------------------------------
 
-egl_connection_t gEGLImpl[2];
+egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS];
 static egl_display_t gDisplay[NUM_DISPLAYS];
 static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_key_t gEGLThreadLocalStorageKey = -1;
@@ -272,35 +273,81 @@
 static __attribute__((noinline))
 void *load_driver(const char* driver, gl_hooks_t* hooks)
 {
+    //LOGD("%s", driver);
+    char scrap[256];
     void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL);
     LOGE_IF(!dso,
             "couldn't load <%s> library (%s)",
             driver, dlerror());
 
     if (dso) {
-        void** curr;
+        // first find the symbol for eglGetProcAddress
+        
+        typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)(
+                const char*);
+        
+        getProcAddressType getProcAddress = 
+            (getProcAddressType)dlsym(dso, "eglGetProcAddress");
+        
+        LOGE_IF(!getProcAddress, 
+                "can't find eglGetProcAddress() in %s", driver);        
+        
+        __eglMustCastToProperFunctionPointerType* curr;
         char const * const * api;
-        gl_hooks_t::gl_t* gl = &hooks->gl;
-        curr = (void**)gl;
-        api = gl_names;
+
+        gl_hooks_t::egl_t* egl = &hooks->egl;
+        curr = (__eglMustCastToProperFunctionPointerType*)egl;
+        api = egl_names;
         while (*api) {
-            void* f = dlsym(dso, *api);
-            //LOGD("<%s> @ 0x%p", *api, f);
+            char const * name = *api;
+            __eglMustCastToProperFunctionPointerType f = 
+                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
             if (f == NULL) {
-                //LOGW("<%s> not found in %s", *api, driver);
-                f = (void*)gl_unimplemented;
+                // couldn't find the entry-point, use eglGetProcAddress()
+                f = getProcAddress(name);
+                if (f == NULL) {
+                    f = (__eglMustCastToProperFunctionPointerType)0;
+                }
             }
             *curr++ = f;
             api++;
         }
-        gl_hooks_t::egl_t* egl = &hooks->egl;
-        curr = (void**)egl;
-        api = egl_names;
+
+        gl_hooks_t::gl_t* gl = &hooks->gl;
+        curr = (__eglMustCastToProperFunctionPointerType*)gl;
+        api = gl_names;
         while (*api) {
-            void* f = dlsym(dso, *api);
+            char const * name = *api;
+            __eglMustCastToProperFunctionPointerType f = 
+                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
             if (f == NULL) {
-                //LOGW("<%s> not found in %s", *api, driver);
-                f = (void*)0;
+                // couldn't find the entry-point, use eglGetProcAddress()
+                f = getProcAddress(name);
+            }
+            if (f == NULL) {
+                // Try without the OES postfix
+                ssize_t index = ssize_t(strlen(name)) - 3;
+                if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) {
+                    strncpy(scrap, name, index);
+                    scrap[index] = 0;
+                    f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
+                    //LOGD_IF(f, "found <%s> instead", scrap);
+                }
+            }
+            if (f == NULL) {
+                // Try with the OES postfix
+                ssize_t index = ssize_t(strlen(name)) - 3;
+                if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) {
+                    strncpy(scrap, name, index);
+                    scrap[index] = 0;
+                    strcat(scrap, "OES");
+                    f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
+                    //LOGD_IF(f, "found <%s> instead", scrap);
+                }
+            }
+            if (f == NULL) {
+                //LOGD("%s", name);
+                f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
             }
             *curr++ = f;
             api++;
@@ -429,18 +476,19 @@
     return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index];
 }
 
-static inline
-egl_surface_t* get_surface(EGLSurface surface)
-{
-    egl_surface_t* s = (egl_surface_t *)surface;
-    return s;
+template<typename NATIVE, typename EGL>
+static inline NATIVE* egl_to_native_cast(EGL arg) {
+    return reinterpret_cast<NATIVE*>(arg);
 }
 
 static inline
-egl_context_t* get_context(EGLContext context)
-{
-    egl_context_t* c = (egl_context_t *)context;
-    return c;
+egl_surface_t* get_surface(EGLSurface surface) {   
+    return egl_to_native_cast<egl_surface_t>(surface);
+}
+
+static inline
+egl_context_t* get_context(EGLContext context) {
+    return egl_to_native_cast<egl_context_t>(context);
 }
 
 static egl_connection_t* validate_display_config(
@@ -451,7 +499,7 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL);
 
     impl = uintptr_t(config)>>24;
-    if (uint32_t(impl) >= 2) {
+    if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) {
         return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL);
     } 
     index = uintptr_t(config) & 0xFFFFFF;
@@ -491,13 +539,8 @@
     return EGL_TRUE;
 }
 
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
 
-using namespace android;
-
-EGLDisplay eglGetDisplay(NativeDisplayType display)
+EGLDisplay egl_init_displays(NativeDisplayType display)
 {
     if (sEarlyInitState) {
         return EGL_NO_DISPLAY;
@@ -510,7 +553,7 @@
     
     EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
     egl_display_t* d = &gDisplay[index];
-        
+
     // dynamically load all our EGL implementations for that display
     // and call into the real eglGetGisplay()
     egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
@@ -573,6 +616,18 @@
     return dpy;
 }
 
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+EGLDisplay eglGetDisplay(NativeDisplayType display)
+{
+    return egl_init_displays(display);
+}
+
 // ----------------------------------------------------------------------------
 // Initialization
 // ----------------------------------------------------------------------------
@@ -594,7 +649,7 @@
     // build our own extension string first, based on the extension we know
     // and the extension supported by our client implementation
     dp->extensionsString = strdup(gExtensionString);
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         cnx->major = -1;
         cnx->minor = -1;
@@ -624,7 +679,7 @@
     }
 
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso && cnx->major>=0 && cnx->minor>=0) {
             EGLint n;
@@ -663,7 +718,7 @@
         return EGL_TRUE;
         
     EGLBoolean res = EGL_FALSE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             cnx->hooks->egl.eglTerminate(dp->dpys[i]);
@@ -706,7 +761,7 @@
         return EGL_TRUE;
     }
     GLint n = 0;
-    for (int j=0 ; j<2 ; j++) {
+    for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) {
         for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) {
             *configs++ = MAKE_CONFIG(j, i);
             config_size--;
@@ -794,7 +849,7 @@
         return res;
     }
 
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglChooseConfig(
@@ -1107,7 +1162,7 @@
 EGLint eglGetError(void)
 {
     EGLint result = EGL_SUCCESS;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         EGLint err = EGL_SUCCESS;
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso)
@@ -1120,8 +1175,15 @@
     return result;
 }
 
-void (*eglGetProcAddress(const char *procname))()
+__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
 {
+    // eglGetProcAddress() could be the very first function called
+    // in which case we must make sure we've initialized ourselves, this
+    // happens the first time egl_get_display() is called.
+    
+    if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY)
+        return NULL;
+
     __eglMustCastToProperFunctionPointerType addr;
     addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
     if (addr) return addr;
@@ -1133,7 +1195,7 @@
     
     addr = 0;
     int slot = -1;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglGetProcAddress) {
@@ -1266,7 +1328,7 @@
     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglSwapInterval) {
@@ -1309,7 +1371,7 @@
 {
     // bind this API on all EGLs
     EGLBoolean res = EGL_TRUE;
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglBindAPI) {
@@ -1324,7 +1386,7 @@
 
 EGLenum eglQueryAPI(void)
 {
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglQueryAPI) {
@@ -1340,7 +1402,7 @@
 
 EGLBoolean eglReleaseThread(void)
 {
-    for (int i=0 ; i<2 ; i++) {
+    for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
             if (cnx->hooks->egl.eglReleaseThread) {
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 865cf44..0057168 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -29,6 +29,7 @@
 #include <cutils/properties.h>
 
 #include "hooks.h"
+#include "egl_impl.h"
 
 using namespace android;
 
@@ -57,13 +58,6 @@
 // Actual GL entry-points
 // ----------------------------------------------------------------------------
 
-#if GL_LOGGER
-#   include "gl_logger.h"
-#   define GL_LOGGER_IMPL(_x) _x
-#else
-#   define GL_LOGGER_IMPL(_x)
-#endif
-
 #undef API_ENTRY
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
@@ -96,21 +90,36 @@
 
     #define CALL_GL_API(_api, ...)                                      \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
-        GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); )                      \
         _c->_api(__VA_ARGS__)
     
     #define CALL_GL_API_RETURN(_api, ...)                               \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
-        GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); )                      \
         return _c->_api(__VA_ARGS__)
 
 #endif
 
+
 extern "C" {
 #include "gl_api.in"
+#include "glext_api.in"
 }
 
 #undef API_ENTRY
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
+
+/*
+ * These GL calls are special because they need to call into EGL to retrieve
+ * some informations before they can execute.
+ */
+
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+}
+
+void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
+{
+}
+
diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in
index 9234ef2..5437d47 100644
--- a/opengl/libs/GLES_CM/gl_api.in
+++ b/opengl/libs/GLES_CM/gl_api.in
@@ -1,532 +1,285 @@
-void API_ENTRY(glActiveTexture)(GLenum texture) {
-    CALL_GL_API(glActiveTexture, texture);
-}
-
 void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) {
     CALL_GL_API(glAlphaFunc, func, ref);
 }
-
-void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) {
-    CALL_GL_API(glAlphaFuncx, func, ref);
-}
-
-void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
-    CALL_GL_API(glBindTexture, target, texture);
-}
-
-void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
-    CALL_GL_API(glBlendFunc, sfactor, dfactor);
-}
-
-void API_ENTRY(glClear)(GLbitfield mask) {
-    CALL_GL_API(glClear, mask);
-}
-
 void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
     CALL_GL_API(glClearColor, red, green, blue, alpha);
 }
-
-void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
-    CALL_GL_API(glClearColorx, red, green, blue, alpha);
-}
-
 void API_ENTRY(glClearDepthf)(GLclampf depth) {
     CALL_GL_API(glClearDepthf, depth);
 }
-
-void API_ENTRY(glClearDepthx)(GLclampx depth) {
-    CALL_GL_API(glClearDepthx, depth);
-}
-
-void API_ENTRY(glClearStencil)(GLint s) {
-    CALL_GL_API(glClearStencil, s);
-}
-
-void API_ENTRY(glClientActiveTexture)(GLenum texture) {
-    CALL_GL_API(glClientActiveTexture, texture);
-}
-
-void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
-    CALL_GL_API(glColor4f, red, green, blue, alpha);
-}
-
-void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    CALL_GL_API(glColor4x, red, green, blue, alpha);
-}
-
-void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
-    CALL_GL_API(glColorMask, r, g, b, a);
-}
-
-void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
-{
-    CALL_GL_API(glColorPointer, size, type, stride, ptr);
-}
-
-void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat,
-                            GLsizei width, GLsizei height, GLint border,
-                            GLsizei imageSize, const GLvoid *data) {
-    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat,
-            width, height, border, imageSize, data);
-}
-
-void API_ENTRY(glCompressedTexSubImage2D)( GLenum target, GLint level, GLint xoffset,
-                                GLint yoffset, GLsizei width, GLsizei height,
-                                GLenum format, GLsizei imageSize,
-                                const GLvoid *data) {
-    CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset,
-            width, height, format, imageSize, data);
-}
-
-void API_ENTRY(glCopyTexImage2D)(  GLenum target, GLint level, GLenum internalformat,
-                        GLint x, GLint y, GLsizei width, GLsizei height,
-                        GLint border) {
-    CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y,
-            width, height, border);
-}
-
-void API_ENTRY(glCopyTexSubImage2D)(   GLenum target, GLint level, GLint xoffset,
-                            GLint yoffset, GLint x, GLint y, GLsizei width,
-                            GLsizei height) {
-    CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y,
-            width, height);
-}
-
-void API_ENTRY(glCullFace)(GLenum mode) {
-    CALL_GL_API(glCullFace, mode);
-}
-
-void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) {
-    CALL_GL_API(glDeleteTextures, n, textures);
-}
-
-void API_ENTRY(glDepthFunc)(GLenum func) {
-    CALL_GL_API(glDepthFunc, func);
-}
-
-void API_ENTRY(glDepthMask)(GLboolean flag) {
-    CALL_GL_API(glDepthMask, flag);
-}
-
-void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
-    CALL_GL_API(glDepthRangef, zNear, zFar);
-}
-
-void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) {
-    CALL_GL_API(glDepthRangex, zNear, zFar);
-}
-
-void API_ENTRY(glDisable)(GLenum cap) {
-    CALL_GL_API(glDisable, cap);
-}
-
-void API_ENTRY(glDisableClientState)(GLenum array) {
-    CALL_GL_API(glDisableClientState, array);
-}
-
-void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
-    CALL_GL_API(glDrawArrays, mode, first, count);
-}
-
-void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count,
-                    GLenum type, const GLvoid *indices) {
-    CALL_GL_API(glDrawElements, mode, count, type, indices);
-}
-
-void API_ENTRY(glEnable)(GLenum cap) {
-    CALL_GL_API(glEnable, cap);
-}
-
-void API_ENTRY(glEnableClientState)(GLenum array) {
-    CALL_GL_API(glEnableClientState, array);
-}
-
-void API_ENTRY(glFinish)(void) {
-    CALL_GL_API(glFinish);
-}
-
-void API_ENTRY(glFlush)(void) {
-    CALL_GL_API(glFlush);
-}
-
-void API_ENTRY(glFogf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glFogf, pname, param);
-}
-
-void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glFogfv, pname, params);
-}
-
-void API_ENTRY(glFogx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glFogx, pname, param);
-}
-
-void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glFogxv, pname, params);
-}
-
-void API_ENTRY(glFrontFace)(GLenum mode) {
-    CALL_GL_API(glFrontFace, mode);
-}
-
-void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
-    CALL_GL_API(glGenTextures, n, textures);
-}
-
-GLenum API_ENTRY(glGetError)(void) {
-    CALL_GL_API_RETURN(glGetError);
-}
-
-void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) {
-    CALL_GL_API(glGetIntegerv, pname, params);
-}
-
-const GLubyte * API_ENTRY(glGetString)(GLenum name) {
-    CALL_GL_API_RETURN(glGetString, name);
-}
-
-void API_ENTRY(glHint)(GLenum target, GLenum mode) {
-    CALL_GL_API(glHint, target, mode);
-}
-
-void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightModelf, pname, param);
-}
-
-void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightModelfv, pname, params);
-}
-
-void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glLightModelx, pname, param);
-}
-
-void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightModelxv, pname, params);
-}
-
-void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightf, light, pname, param);
-}
-
-void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightfv, light, pname, params);
-}
-
-void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) {
-    CALL_GL_API(glLightx, light, pname, param);
-}
-
-void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightxv, light, pname, params);
-}
-
-void API_ENTRY(glLineWidth)(GLfloat width) {
-    CALL_GL_API(glLineWidth, width);
-}
-
-void API_ENTRY(glLineWidthx)(GLfixed width) {
-    CALL_GL_API(glLineWidthx, width);
-}
-
-void API_ENTRY(glLoadIdentity)(void) {
-    CALL_GL_API(glLoadIdentity);
-}
-
-void API_ENTRY(glLoadMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glLoadMatrixf, m);
-}
-
-void API_ENTRY(glLoadMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glLoadMatrixx, m);
-}
-
-void API_ENTRY(glLogicOp)(GLenum opcode) {
-    CALL_GL_API(glLogicOp, opcode);
-}
-
-void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) {
-    CALL_GL_API(glMaterialf, face, pname, param);
-}
-
-void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glMaterialfv, face, pname, params);
-}
-
-void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) {
-    CALL_GL_API(glMaterialx, face, pname, param);
-}
-
-void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glMaterialxv, face, pname, params);
-}
-
-void API_ENTRY(glMatrixMode)(GLenum mode) {
-    CALL_GL_API(glMatrixMode, mode);
-}
-
-void API_ENTRY(glMultMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glMultMatrixf, m);
-}
-
-void API_ENTRY(glMultMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glMultMatrixx, m);
-}
-
-void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
-    CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q);
-}
-
-void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
-    CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q);
-}
-
-void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) {
-    CALL_GL_API(glNormal3f, nx, ny, nz);
-}
-
-void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) {
-    CALL_GL_API(glNormal3x, nx, ny, nz);
-}
-
-void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glNormalPointer, type, stride, pointer);
-}
-
-void API_ENTRY(glOrthof)(  GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glOrthox)(  GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar);
-}
-
-void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
-    CALL_GL_API(glPixelStorei, pname, param);
-}
-
-void API_ENTRY(glPointSize)(GLfloat size) {
-    CALL_GL_API(glPointSize, size);
-}
-
-void API_ENTRY(glPointSizex)(GLfixed size) {
-    CALL_GL_API(glPointSizex, size);
-}
-
-void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
-    CALL_GL_API(glPolygonOffset, factor, units);
-}
-
-void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) {
-    CALL_GL_API(glPolygonOffsetx, factor, units);
-}
-
-void API_ENTRY(glPopMatrix)(void) {
-    CALL_GL_API(glPopMatrix);
-}
-
-void API_ENTRY(glPushMatrix)(void) {
-    CALL_GL_API(glPushMatrix);
-}
-
-void API_ENTRY(glReadPixels)(  GLint x, GLint y, GLsizei width, GLsizei height,
-                    GLenum format, GLenum type, GLvoid *pixels) {
-    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
-}
-
-void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glRotatef, angle, x, y, z);
-}
-
-void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glRotatex, angle, x, y, z);
-}
-
-void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
-    CALL_GL_API(glSampleCoverage, value, invert);
-}
-
-void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) {
-    CALL_GL_API(glSampleCoveragex, value, invert);
-}
-
-void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glScalef, x, y, z);
-}
-
-void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glScalex, x, y, z);
-}
-
-void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glScissor, x, y, width, height);
-}
-
-void API_ENTRY(glShadeModel)(GLenum mode) {
-    CALL_GL_API(glShadeModel, mode);
-}
-
-void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
-    CALL_GL_API(glStencilFunc, func, ref, mask);
-}
-
-void API_ENTRY(glStencilMask)(GLuint mask) {
-    CALL_GL_API(glStencilMask, mask);
-}
-
-void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
-    CALL_GL_API(glStencilOp, fail, zfail, zpass);
-}
-
-void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glTexCoordPointer, size, type, stride, pointer);
-}
-
-void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) {
-    CALL_GL_API(glTexEnvf, target, pname, param);
-}
-
-void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexEnvfv, target, pname, params);
-}
-
-void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexEnvx, target, pname, param);
-}
-
-void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glTexEnvxv, target, pname, params);
-}
-
-void API_ENTRY(glTexImage2D)(  GLenum target, GLint level, GLint internalformat,
-                    GLsizei width, GLsizei height, GLint border, GLenum format,
-                    GLenum type, const GLvoid *pixels) {
-    CALL_GL_API(glTexImage2D, target, level, internalformat, width, height,
-            border, format, type, pixels);
-}
-
-void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
-    CALL_GL_API(glTexParameterf, target, pname, param);
-}
-
-void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexParameterx, target, pname, param);
-}
-
-void API_ENTRY(glTexSubImage2D)(   GLenum target, GLint level, GLint xoffset,
-                        GLint yoffset, GLsizei width, GLsizei height,
-                        GLenum format, GLenum type, const GLvoid *pixels) {
-    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset,
-            width, height, format, type, pixels);
-}
-
-void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glTranslatef, x, y, z);
-}
-
-void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glTranslatex, x, y, z);
-}
-
-void API_ENTRY(glVertexPointer)(   GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glVertexPointer, size, type, stride, pointer);
-}
-
-void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glViewport, x, y, width, height);
-}
-
-// ES 1.1
 void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) {
     CALL_GL_API(glClipPlanef, plane, equation);
 }
-void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) {
-    CALL_GL_API(glClipPlanex, plane, equation);
+void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
+    CALL_GL_API(glColor4f, red, green, blue, alpha);
 }
-void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
-    CALL_GL_API(glBindBuffer, target, buffer);
+void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
+    CALL_GL_API(glDepthRangef, zNear, zFar);
 }
-void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
-    CALL_GL_API(glBufferData, target, size, data, usage);
+void API_ENTRY(glFogf)(GLenum pname, GLfloat param) {
+    CALL_GL_API(glFogf, pname, param);
 }
-void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
-    CALL_GL_API(glBufferSubData, target, offset, size, data);
+void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glFogfv, pname, params);
 }
-void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) {
-    CALL_GL_API(glDeleteBuffers, n, buffers);
-}
-void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) {
-    CALL_GL_API(glGenBuffers, n, buffers);
-}
-void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) {
-    CALL_GL_API(glGetBooleanv, pname, params);
-}
-void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetFixedv, pname, params);
-}
-void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetFloatv, pname, params);
-}
-void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
-    CALL_GL_API(glGetPointerv, pname, params);
-}
-void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
-    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar);
 }
 void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) {
     CALL_GL_API(glGetClipPlanef, pname, eqn);
 }
-void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) {
-    CALL_GL_API(glGetClipPlanex, pname, eqn);
-}
-void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetLightxv, light, pname, params);
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) {
+    CALL_GL_API(glGetFloatv, pname, params);
 }
 void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetLightfv, light, pname, params);
 }
-void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetMaterialxv, face, pname, params);
-}
 void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetMaterialfv, face, pname, params);
 }
 void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetTexEnvfv, env, pname, params);
 }
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
+    CALL_GL_API(glGetTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) {
+    CALL_GL_API(glLightModelf, pname, param);
+}
+void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glLightModelfv, pname, params);
+}
+void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) {
+    CALL_GL_API(glLightf, light, pname, param);
+}
+void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glLightfv, light, pname, params);
+}
+void API_ENTRY(glLineWidth)(GLfloat width) {
+    CALL_GL_API(glLineWidth, width);
+}
+void API_ENTRY(glLoadMatrixf)(const GLfloat *m) {
+    CALL_GL_API(glLoadMatrixf, m);
+}
+void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) {
+    CALL_GL_API(glMaterialf, face, pname, param);
+}
+void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glMaterialfv, face, pname, params);
+}
+void API_ENTRY(glMultMatrixf)(const GLfloat *m) {
+    CALL_GL_API(glMultMatrixf, m);
+}
+void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
+    CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q);
+}
+void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) {
+    CALL_GL_API(glNormal3f, nx, ny, nz);
+}
+void API_ENTRY(glOrthof)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) {
+    CALL_GL_API(glPointParameterf, pname, param);
+}
+void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glPointParameterfv, pname, params);
+}
+void API_ENTRY(glPointSize)(GLfloat size) {
+    CALL_GL_API(glPointSize, size);
+}
+void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
+    CALL_GL_API(glPolygonOffset, factor, units);
+}
+void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glRotatef, angle, x, y, z);
+}
+void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glScalef, x, y, z);
+}
+void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexEnvf, target, pname, param);
+}
+void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glTexEnvfv, target, pname, params);
+}
+void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexParameterf, target, pname, param);
+}
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glTexParameterfv, target, pname, params);
+}
+void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) {
+    CALL_GL_API(glTranslatef, x, y, z);
+}
+void API_ENTRY(glActiveTexture)(GLenum texture) {
+    CALL_GL_API(glActiveTexture, texture);
+}
+void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) {
+    CALL_GL_API(glAlphaFuncx, func, ref);
+}
+void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
+    CALL_GL_API(glBindBuffer, target, buffer);
+}
+void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
+    CALL_GL_API(glBindTexture, target, texture);
+}
+void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
+    CALL_GL_API(glBlendFunc, sfactor, dfactor);
+}
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) {
+    CALL_GL_API(glBufferData, target, size, data, usage);
+}
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) {
+    CALL_GL_API(glBufferSubData, target, offset, size, data);
+}
+void API_ENTRY(glClear)(GLbitfield mask) {
+    CALL_GL_API(glClear, mask);
+}
+void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
+    CALL_GL_API(glClearColorx, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthx)(GLclampx depth) {
+    CALL_GL_API(glClearDepthx, depth);
+}
+void API_ENTRY(glClearStencil)(GLint s) {
+    CALL_GL_API(glClearStencil, s);
+}
+void API_ENTRY(glClientActiveTexture)(GLenum texture) {
+    CALL_GL_API(glClientActiveTexture, texture);
+}
+void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) {
+    CALL_GL_API(glClipPlanex, plane, equation);
+}
+void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
+    CALL_GL_API(glColor4ub, red, green, blue, alpha);
+}
+void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
+    CALL_GL_API(glColor4x, red, green, blue, alpha);
+}
+void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+    CALL_GL_API(glColorMask, red, green, blue, alpha);
+}
+void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glColorPointer, size, type, stride, pointer);
+}
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) {
+    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
+}
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) {
+    CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
+    CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, width, height, border);
+}
+void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, width, height);
+}
+void API_ENTRY(glCullFace)(GLenum mode) {
+    CALL_GL_API(glCullFace, mode);
+}
+void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint *buffers) {
+    CALL_GL_API(glDeleteBuffers, n, buffers);
+}
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) {
+    CALL_GL_API(glDeleteTextures, n, textures);
+}
+void API_ENTRY(glDepthFunc)(GLenum func) {
+    CALL_GL_API(glDepthFunc, func);
+}
+void API_ENTRY(glDepthMask)(GLboolean flag) {
+    CALL_GL_API(glDepthMask, flag);
+}
+void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) {
+    CALL_GL_API(glDepthRangex, zNear, zFar);
+}
+void API_ENTRY(glDisable)(GLenum cap) {
+    CALL_GL_API(glDisable, cap);
+}
+void API_ENTRY(glDisableClientState)(GLenum array) {
+    CALL_GL_API(glDisableClientState, array);
+}
+void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
+    CALL_GL_API(glDrawArrays, mode, first, count);
+}
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
+    CALL_GL_API(glDrawElements, mode, count, type, indices);
+}
+void API_ENTRY(glEnable)(GLenum cap) {
+    CALL_GL_API(glEnable, cap);
+}
+void API_ENTRY(glEnableClientState)(GLenum array) {
+    CALL_GL_API(glEnableClientState, array);
+}
+void API_ENTRY(glFinish)(void) {
+    CALL_GL_API(glFinish);
+}
+void API_ENTRY(glFlush)(void) {
+    CALL_GL_API(glFlush);
+}
+void API_ENTRY(glFogx)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glFogx, pname, param);
+}
+void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glFogxv, pname, params);
+}
+void API_ENTRY(glFrontFace)(GLenum mode) {
+    CALL_GL_API(glFrontFace, mode);
+}
+void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) {
+    CALL_GL_API(glGetBooleanv, pname, params);
+}
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
+}
+void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) {
+    CALL_GL_API(glGetClipPlanex, pname, eqn);
+}
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint *buffers) {
+    CALL_GL_API(glGenBuffers, n, buffers);
+}
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
+    CALL_GL_API(glGenTextures, n, textures);
+}
+GLenum API_ENTRY(glGetError)(void) {
+    CALL_GL_API_RETURN(glGetError);
+}
+void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetFixedv, pname, params);
+}
+void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) {
+    CALL_GL_API(glGetIntegerv, pname, params);
+}
+void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetLightxv, light, pname, params);
+}
+void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetMaterialxv, face, pname, params);
+}
+void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
+    CALL_GL_API(glGetPointerv, pname, params);
+}
+const GLubyte * API_ENTRY(glGetString)(GLenum name) {
+    CALL_GL_API_RETURN(glGetString, name);
+}
 void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexEnviv, env, pname, params);
 }
 void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexEnvxv, env, pname, params);
 }
-void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetTexParameterfv, target, pname, params);
-}
 void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexParameteriv, target, pname, params);
 }
 void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexParameterxv, target, pname, params);
 }
+void API_ENTRY(glHint)(GLenum target, GLenum mode) {
+    CALL_GL_API(glHint, target, mode);
+}
 GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) {
     CALL_GL_API_RETURN(glIsBuffer, buffer);
 }
@@ -536,11 +289,56 @@
 GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
     CALL_GL_API_RETURN(glIsTexture, texture);
 }
-void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glPointParameterf, pname, param);
+void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightModelx, pname, param);
 }
-void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glPointParameterfv, pname, params);
+void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightModelxv, pname, params);
+}
+void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightx, light, pname, param);
+}
+void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightxv, light, pname, params);
+}
+void API_ENTRY(glLineWidthx)(GLfixed width) {
+    CALL_GL_API(glLineWidthx, width);
+}
+void API_ENTRY(glLoadIdentity)(void) {
+    CALL_GL_API(glLoadIdentity);
+}
+void API_ENTRY(glLoadMatrixx)(const GLfixed *m) {
+    CALL_GL_API(glLoadMatrixx, m);
+}
+void API_ENTRY(glLogicOp)(GLenum opcode) {
+    CALL_GL_API(glLogicOp, opcode);
+}
+void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) {
+    CALL_GL_API(glMaterialx, face, pname, param);
+}
+void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glMaterialxv, face, pname, params);
+}
+void API_ENTRY(glMatrixMode)(GLenum mode) {
+    CALL_GL_API(glMatrixMode, mode);
+}
+void API_ENTRY(glMultMatrixx)(const GLfixed *m) {
+    CALL_GL_API(glMultMatrixx, m);
+}
+void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
+    CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q);
+}
+void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) {
+    CALL_GL_API(glNormal3x, nx, ny, nz);
+}
+void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glNormalPointer, type, stride, pointer);
+}
+void API_ENTRY(glOrthox)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
+    CALL_GL_API(glPixelStorei, pname, param);
 }
 void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) {
     CALL_GL_API(glPointParameterx, pname, param);
@@ -548,59 +346,90 @@
 void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) {
     CALL_GL_API(glPointParameterxv, pname, params);
 }
-void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
-    CALL_GL_API(glColor4ub, red, green, blue, alpha);
+void API_ENTRY(glPointSizex)(GLfixed size) {
+    CALL_GL_API(glPointSizex, size);
+}
+void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) {
+    CALL_GL_API(glPolygonOffsetx, factor, units);
+}
+void API_ENTRY(glPopMatrix)(void) {
+    CALL_GL_API(glPopMatrix);
+}
+void API_ENTRY(glPushMatrix)(void) {
+    CALL_GL_API(glPushMatrix);
+}
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
+    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
+}
+void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glRotatex, angle, x, y, z);
+}
+void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
+    CALL_GL_API(glSampleCoverage, value, invert);
+}
+void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) {
+    CALL_GL_API(glSampleCoveragex, value, invert);
+}
+void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glScalex, x, y, z);
+}
+void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glScissor, x, y, width, height);
+}
+void API_ENTRY(glShadeModel)(GLenum mode) {
+    CALL_GL_API(glShadeModel, mode);
+}
+void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glStencilFunc, func, ref, mask);
+}
+void API_ENTRY(glStencilMask)(GLuint mask) {
+    CALL_GL_API(glStencilMask, mask);
+}
+void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
+    CALL_GL_API(glStencilOp, fail, zfail, zpass);
+}
+void API_ENTRY(glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glTexCoordPointer, size, type, stride, pointer);
 }
 void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glTexEnvi, target, pname, param);
 }
+void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexEnvx, target, pname, param);
+}
 void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) {
     CALL_GL_API(glTexEnviv, target, pname, params);
 }
-
-void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexParameterfv, target, pname, params);
+void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexEnvxv, target, pname, params);
 }
-
-void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
-    CALL_GL_API(glTexParameteriv, target, pname, params);
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
+    CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
 }
-
 void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glTexParameteri, target, pname, param);
 }
+void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexParameterx, target, pname, param);
+}
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
+    CALL_GL_API(glTexParameteriv, target, pname, params);
+}
 void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glTexParameterxv, target, pname, params);
 }
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {
+    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glTranslatex, x, y, z);
+}
+void API_ENTRY(glVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glVertexPointer, size, type, stride, pointer);
+}
+void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
+    CALL_GL_API(glViewport, x, y, width, height);
+}
 void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) {
     CALL_GL_API(glPointSizePointerOES, type, stride, pointer);
 }
-
-// Extensions
-void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) {
-    CALL_GL_API(glDrawTexsOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) {
-    CALL_GL_API(glDrawTexiOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) {
-    CALL_GL_API(glDrawTexfOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) {
-    CALL_GL_API(glDrawTexxOES, x, y, z, w, h);
-}
-void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) {
-    CALL_GL_API(glDrawTexsvOES, coords);
-}
-void API_ENTRY(glDrawTexivOES)(const GLint* coords) {
-    CALL_GL_API(glDrawTexivOES, coords);
-}
-void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) {
-    CALL_GL_API(glDrawTexfvOES, coords);
-}
-void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) {
-    CALL_GL_API(glDrawTexxvOES, coords);
-}
-GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) {
-    CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent);
-}
diff --git a/opengl/libs/GLES_CM/gl_logger.cpp b/opengl/libs/GLES_CM/gl_logger.cpp
deleted file mode 100644
index 27be5c9..0000000
--- a/opengl/libs/GLES_CM/gl_logger.cpp
+++ /dev/null
@@ -1,1060 +0,0 @@
-/*
- ** Copyright 2007, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- **     http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#define LOG_TAG "GLLogger"
-
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <dlfcn.h>
-
-#include <sys/ioctl.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <utils/String8.h>
-
-#include "gl_logger.h"
-
-#undef NELEM
-#define NELEM(x) (sizeof(x)/sizeof(*(x)))
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-template<typename T>
-static int binarySearch(T const sortedArray[], int first, int last, EGLint key)
-{
-   while (first <= last) {
-       int mid = (first + last) / 2;
-       if (key > sortedArray[mid].key) {
-           first = mid + 1;
-       } else if (key < sortedArray[mid].key) {
-           last = mid - 1;
-       } else {
-           return mid;
-       }
-   }
-   return -1;
-}
-
-struct pair_t {
-    const char* name;
-    int         key;
-};
-
-static const pair_t gEnumMap[] = {
-    #define GLENUM(NAME, VALUE) { #NAME, VALUE },
-    #include "gl_enums.in"
-    #undef GLENUM
-};
-
-// ----------------------------------------------------------------------------
-
-template<typename TYPE>
-class GLLogValue {
-public:
-    GLLogValue(TYPE value) : mValue(value) { }
-    const TYPE& getValue() const { return mValue; }
-    String8 toString() const {
-        return convertToString(mValue);
-    }
-private:
-    const TYPE& mValue;
-    String8 convertToString(unsigned int v) const {
-        char buf[16];
-        snprintf(buf, 16, "%u", v);
-        return String8(buf);
-    }
-    String8 convertToString(unsigned long v) const {
-        char buf[16];
-        snprintf(buf, 16, "%lu", v);
-        return String8(buf);
-    }
-    String8 convertToString(int v) const {
-        char buf[16];
-        snprintf(buf, 16, "%d", v);
-        return String8(buf);
-    }
-    String8 convertToString(long v) const {
-        char buf[16];
-        snprintf(buf, 16, "%ld", v);
-        return String8(buf);
-    }
-    String8 convertToString(float v) const {
-        char buf[16];
-        snprintf(buf, 16, "%f", v);
-        return String8(buf);
-    }
-    String8 convertToString(void const* v) const {
-        char buf[16];
-        snprintf(buf, 16, "%p", v);
-        return String8(buf);
-    }
-};
-
-class GLLogEnum : public GLLogValue<GLenum> {
-public:
-    GLLogEnum(GLenum v) : GLLogValue<GLenum>(v) { }
-    String8 toString() const {
-        GLenum v = getValue();
-        int i = binarySearch<pair_t>(gEnumMap, 0, NELEM(gEnumMap)-1, v);
-        if (i >= 0) {
-            return String8(gEnumMap[i].name);
-        } else {
-            char buf[16];
-            snprintf(buf, 16, "0x%04x", v);
-            return String8(buf);
-        }
-    }
-};
-
-class GLLogClearBitfield : public GLLogValue<GLbitfield> {
-public:
-    GLLogClearBitfield(GLbitfield v) : GLLogValue<GLbitfield>(v) { }
-    String8 toString() const {
-        char buf[16];
-        snprintf(buf, 16, "0x%08x", getValue());
-        return String8(buf);
-    }
-};
-
-class GLLogBool : public GLLogValue<GLboolean> {
-public:
-    GLLogBool(GLboolean v) : GLLogValue<GLboolean>(v) { }
-    String8 toString() const {
-        GLboolean v = getValue();
-        if (v == GL_TRUE)   return String8("GL_TRUE");
-        if (v == GL_FALSE)  return String8("GL_FALSE");
-        return GLLogValue<GLboolean>::toString();
-    }
-};
-
-class GLLogFixed : public GLLogValue<GLfixed> {
-public:
-    GLLogFixed(GLfixed v) : GLLogValue<GLfixed>(v) { }
-    String8 toString() const {
-        char buf[16];
-        snprintf(buf, 16, "0x%08x", getValue());
-        return String8(buf);
-    }
-};
-
-
-template <typename TYPE>
-class GLLogBuffer : public GLLogValue<TYPE *> {
-public:
-    GLLogBuffer(TYPE* buffer, size_t count = -1)
-        : GLLogValue<TYPE*>(buffer)
-    { // output buffer
-    }
-    GLLogBuffer(TYPE const* buffer, size_t count = -1)
-    : GLLogValue<TYPE*>(const_cast<TYPE*>(buffer))
-    { // input buffer
-    }
-};
-
-class GLLog
-{
-public:
-    GLLog(const char* name) : mNumParams(0) {
-        mString.append(name);
-        mString.append("(");
-    }
-
-    ~GLLog() {
-        LOGD("%s);", mString.string());
-    }
-
-    GLLog& operator << (unsigned char v) {
-        return *this << GLLogValue<unsigned int>(v);
-    }
-    GLLog& operator << (short v) {
-        return *this << GLLogValue<unsigned int>(v);
-    }
-    GLLog& operator << (unsigned int v) {
-        return *this << GLLogValue<unsigned int>(v);
-    }
-    GLLog& operator << (int v) {
-        return *this << GLLogValue<int>(v);
-    }
-    GLLog& operator << (long v) {
-        return *this << GLLogValue<long>(v);
-    }
-    GLLog& operator << (unsigned long v) {
-        return *this << GLLogValue<unsigned long>(v);
-    }
-    GLLog& operator << (float v) {
-        return *this << GLLogValue<float>(v);
-    }
-    GLLog& operator << (const void* v) {
-        return *this << GLLogValue<const void* >(v);
-    }
-
-    template <typename TYPE>
-    GLLog& operator << (const TYPE& rhs) {
-        if (mNumParams > 0)
-            mString.append(", ");
-        mString.append(rhs.toString());
-        mNumParams++;
-        return *this;
-    }
-
-    const String8& string() const { return mString; }
-private:
-    GLLog(const GLLog&);
-
-    String8 mString;
-    int mNumParams;
-};
-
-#define API_ENTRY(api)                      log_##api
-#define CALL_GL_API(_x, ...)
-#define CALL_GL_API_RETURN(_x, ...)         return(0);
-
-void API_ENTRY(glActiveTexture)(GLenum texture) {
-    CALL_GL_API(glActiveTexture, texture);
-    GLLog("glActiveTexture") << GLLogEnum(texture);
-}
-
-void API_ENTRY(glAlphaFunc)(GLenum func, GLclampf ref) {
-    CALL_GL_API(glAlphaFunc, func, ref);
-    GLLog("glAlphaFunc") << GLLogEnum(func) << ref;
-}
-
-void API_ENTRY(glAlphaFuncx)(GLenum func, GLclampx ref) {
-    CALL_GL_API(glAlphaFuncx, func, ref);
-    GLLog("glAlphaFuncx") << GLLogEnum(func) << GLLogFixed(ref);
-}
-
-void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) {
-    CALL_GL_API(glBindTexture, target, texture);
-    GLLog("glBindTexture") << GLLogEnum(target) << texture;
-}
-
-void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
-    CALL_GL_API(glBlendFunc, sfactor, dfactor);
-    GLLog("glBlendFunc") << GLLogEnum(sfactor) << GLLogEnum(dfactor);
-}
-
-void API_ENTRY(glClear)(GLbitfield mask) {
-    CALL_GL_API(glClear, mask);
-    GLLog("glClear") << GLLogClearBitfield(mask);
-}
-
-void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
-    CALL_GL_API(glClearColor, red, green, blue, alpha);
-    GLLog("glClearColor") << red << green << blue << alpha;
-}
-
-void API_ENTRY(glClearColorx)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
-    CALL_GL_API(glClearColorx, red, green, blue, alpha);
-    GLLog("glClearColorx") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha);
-}
-
-void API_ENTRY(glClearDepthf)(GLclampf depth) {
-    CALL_GL_API(glClearDepthf, depth);
-    GLLog("glClearDepthf") << depth;
-}
-
-void API_ENTRY(glClearDepthx)(GLclampx depth) {
-    CALL_GL_API(glClearDepthx, depth);
-    GLLog("glClearDepthx") << GLLogFixed(depth);
-}
-
-void API_ENTRY(glClearStencil)(GLint s) {
-    CALL_GL_API(glClearStencil, s);
-    GLLog("glClearStencil") << s;
-}
-
-void API_ENTRY(glClientActiveTexture)(GLenum texture) {
-    CALL_GL_API(glClientActiveTexture, texture);
-    GLLog("glClientActiveTexture") << GLLogEnum(texture);
-}
-
-void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
-    CALL_GL_API(glColor4f, red, green, blue, alpha);
-    GLLog("glColor4f") << red << green << blue << alpha;
-}
-
-void API_ENTRY(glColor4x)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    CALL_GL_API(glColor4x, red, green, blue, alpha);
-    GLLog("glColor4x") << GLLogFixed(red) << GLLogFixed(green) << GLLogFixed(blue) << GLLogFixed(alpha);
-}
-
-void API_ENTRY(glColorMask)(GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
-    CALL_GL_API(glColorMask, r, g, b, a);
-    GLLog("glColorMask") << GLLogBool(r) << GLLogBool(g) << GLLogBool(b) << GLLogBool(a);
-}
-
-void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
-{
-    CALL_GL_API(glColorPointer, size, type, stride, ptr);
-    GLLog("glColorPointer") << size << GLLogEnum(type) << stride << ptr;
-}
-
-void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat,
-                            GLsizei width, GLsizei height, GLint border,
-                            GLsizei imageSize, const GLvoid *data) {
-    CALL_GL_API(glCompressedTexImage2D, target, level, internalformat,
-            width, height, border, imageSize, data);
-    GLLog("glCompressedTexImage2D")
-                << GLLogEnum(target) << level << GLLogEnum(internalformat)
-                << width << height << border << imageSize << data;
-}
-
-void API_ENTRY(glCompressedTexSubImage2D)( GLenum target, GLint level, GLint xoffset,
-                                GLint yoffset, GLsizei width, GLsizei height,
-                                GLenum format, GLsizei imageSize,
-                                const GLvoid *data) {
-    CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset,
-            width, height, format, imageSize, data);
-    GLLog("glCompressedTexSubImage2D")
-            << GLLogEnum(target) << level << xoffset << yoffset
-            << width << height << GLLogEnum(format) << imageSize << data;
-}
-
-void API_ENTRY(glCopyTexImage2D)(  GLenum target, GLint level, GLenum internalformat,
-                        GLint x, GLint y, GLsizei width, GLsizei height,
-                        GLint border) {
-    CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y,
-            width, height, border);
-    GLLog("glCopyTexImage2D")
-            << GLLogEnum(target) << level << GLLogEnum(internalformat)
-            << x << y << width << height << border;
-}
-
-void API_ENTRY(glCopyTexSubImage2D)(   GLenum target, GLint level, GLint xoffset,
-                            GLint yoffset, GLint x, GLint y, GLsizei width,
-                            GLsizei height) {
-    CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y,
-            width, height);
-    GLLog("glCopyTexSubImage2D")
-            << GLLogEnum(target) << level << xoffset << yoffset
-            << x << y << width << height;
-}
-
-void API_ENTRY(glCullFace)(GLenum mode) {
-    CALL_GL_API(glCullFace, mode);
-    GLLog("glCullFace") << GLLogEnum(mode);
-}
-
-void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) {
-    CALL_GL_API(glDeleteTextures, n, textures);
-    GLLog("glDeleteTextures") << n << GLLogBuffer<GLuint>(textures, n);
-}
-
-void API_ENTRY(glDepthFunc)(GLenum func) {
-    CALL_GL_API(glDepthFunc, func);
-    GLLog("glDepthFunc") << GLLogEnum(func);
-}
-
-void API_ENTRY(glDepthMask)(GLboolean flag) {
-    CALL_GL_API(glDepthMask, flag);
-    GLLog("glDepthMask") << GLLogBool(flag);
-}
-
-void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) {
-    CALL_GL_API(glDepthRangef, zNear, zFar);
-    GLLog("glDepthRangef") << zNear << zFar;
-}
-
-void API_ENTRY(glDepthRangex)(GLclampx zNear, GLclampx zFar) {
-    CALL_GL_API(glDepthRangex, zNear, zFar);
-    GLLog("glDepthRangex") << GLLogFixed(zNear) << GLLogFixed(zFar);
-}
-
-void API_ENTRY(glDisable)(GLenum cap) {
-    CALL_GL_API(glDisable, cap);
-    GLLog("glDisable") << GLLogEnum(cap);
-}
-
-void API_ENTRY(glDisableClientState)(GLenum array) {
-    CALL_GL_API(glDisableClientState, array);
-    GLLog("glDisableClientState") << GLLogEnum(array);
-}
-
-void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
-    CALL_GL_API(glDrawArrays, mode, first, count);
-    GLLog("glDrawArrays") << GLLogEnum(mode) << first << count;
-}
-
-void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count,
-                    GLenum type, const GLvoid *indices) {
-    CALL_GL_API(glDrawElements, mode, count, type, indices);
-    GLLog log("glDrawElements");
-    log << GLLogEnum(mode) << count << GLLogEnum(type);
-    if (type == GL_UNSIGNED_BYTE) {
-        log << GLLogBuffer<GLubyte>(static_cast<const GLubyte*>(indices), count);
-    } else {
-        log << GLLogBuffer<GLushort>(static_cast<const GLushort*>(indices), count);
-    }
-    log;
-}
-
-void API_ENTRY(glEnable)(GLenum cap) {
-    CALL_GL_API(glEnable, cap);
-    GLLog("glEnable") << GLLogEnum(cap);
-}
-
-void API_ENTRY(glEnableClientState)(GLenum array) {
-    CALL_GL_API(glEnableClientState, array);
-    GLLog("glEnableClientState") << GLLogEnum(array);
-}
-
-void API_ENTRY(glFinish)(void) {
-    CALL_GL_API(glFinish);
-    GLLog("glFinish");
-}
-
-void API_ENTRY(glFlush)(void) {
-    CALL_GL_API(glFlush);
-    GLLog("glFlush");
-}
-
-void API_ENTRY(glFogf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glFogf, pname, param);
-    GLLog("glFogf") << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glFogfv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glFogfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glFogx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glFogx, pname, param);
-    GLLog("glFogx") << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glFogxv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glFogfx") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glFrontFace)(GLenum mode) {
-    CALL_GL_API(glFrontFace, mode);
-    GLLog("glFrontFace") << GLLogEnum(mode);
- }
-
-void API_ENTRY(glFrustumf)(GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glFrustumf, left, right, bottom, top, zNear, zFar);
-    GLLog("glFrustumf") << left << right << bottom << top << zNear << zFar;
-}
-
-void API_ENTRY(glFrustumx)(GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glFrustumx, left, right, bottom, top, zNear, zFar);
-    GLLog("glFrustumx")
-            << GLLogFixed(left) << GLLogFixed(right)
-            << GLLogFixed(bottom) << GLLogFixed(top)
-            << GLLogFixed(zNear) << GLLogFixed(zFar);
-}
-
-void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
-    CALL_GL_API(glGenTextures, n, textures);
-    GLLog("glGenTextures") << n << GLLogBuffer<GLuint>(textures, n);
-}
-
-GLenum API_ENTRY(glGetError)(void) {
-    GLLog("glGetError");
-    CALL_GL_API_RETURN(glGetError);
-}
-
-void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *params) {
-    CALL_GL_API(glGetIntegerv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetIntegerv") << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-
-const GLubyte * API_ENTRY(glGetString)(GLenum name) {
-    GLLog("glGetString") << GLLogEnum(name);
-    CALL_GL_API_RETURN(glGetString, name);
-}
-
-void API_ENTRY(glHint)(GLenum target, GLenum mode) {
-    CALL_GL_API(glHint, target, mode);
-    GLLog("GLenum") << GLLogEnum(target) << GLLogEnum(mode);
-}
-
-void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightModelf, pname, param);
-    GLLog("glLightModelf") << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightModelfv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightModelfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glLightModelx, pname, param);
-    GLLog("glLightModelx") << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightModelxv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightModelxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) {
-    CALL_GL_API(glLightf, light, pname, param);
-    GLLog("glLightf") << GLLogEnum(light) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glLightfv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) {
-   CALL_GL_API(glLightx, light, pname, param);
-   GLLog("glLightx") << GLLogEnum(light) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glLightxv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glLineWidth)(GLfloat width) {
-    CALL_GL_API(glLineWidth, width);
-    GLLog("glLineWidth") << width;
-}
-
-void API_ENTRY(glLineWidthx)(GLfixed width) {
-    CALL_GL_API(glLineWidthx, width);
-    GLLog("glLineWidth") << GLLogFixed(width);
-}
-
-void API_ENTRY(glLoadIdentity)(void) {
-    CALL_GL_API(glLoadIdentity);
-    GLLog("glLoadIdentity");
-}
-
-void API_ENTRY(glLoadMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glLoadMatrixf, m);
-    GLLog("glLoadMatrixf") << GLLogBuffer<GLfloat>(m, 16);
-}
-
-void API_ENTRY(glLoadMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glLoadMatrixx, m);
-    GLLog("glLoadMatrixx") << GLLogBuffer<GLfixed>(m, 16);
-}
-
-void API_ENTRY(glLogicOp)(GLenum opcode) {
-    CALL_GL_API(glLogicOp, opcode);
-    GLLog("glLogicOp") << GLLogEnum(opcode);
-}
-
-void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) {
-    CALL_GL_API(glMaterialf, face, pname, param);
-    GLLog("glMaterialf") << GLLogEnum(face) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glMaterialfv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) {
-    CALL_GL_API(glMaterialx, face, pname, param);
-    GLLog("glMaterialx") << GLLogEnum(face) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glMaterialxv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glMatrixMode)(GLenum mode) {
-    CALL_GL_API(glMatrixMode, mode);
-    GLLog("glMatrixMode") << GLLogEnum(mode);
-}
-
-void API_ENTRY(glMultMatrixf)(const GLfloat *m) {
-    CALL_GL_API(glMultMatrixf, m);
-    GLLog("glMultMatrixf") << GLLogBuffer<GLfloat>(m, 16);
-}
-
-void API_ENTRY(glMultMatrixx)(const GLfixed *m) {
-    CALL_GL_API(glMultMatrixx, m);
-    GLLog("glMultMatrixx") << GLLogBuffer<GLfixed>(m, 16);
-}
-
-void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
-    CALL_GL_API(glMultiTexCoord4f, target, s, t, r, q);
-    GLLog("glMultiTexCoord4f") << GLLogEnum(target) << s << t << r << q;
-}
-
-void API_ENTRY(glMultiTexCoord4x)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
-    CALL_GL_API(glMultiTexCoord4x, target, s, t, r, q);
-    GLLog("glMultiTexCoord4x") << GLLogEnum(target)
-        << GLLogFixed(s) << GLLogFixed(t) << GLLogFixed(r) << GLLogFixed(q);
-}
-
-void API_ENTRY(glNormal3f)(GLfloat nx, GLfloat ny, GLfloat nz) {
-    CALL_GL_API(glNormal3f, nx, ny, nz);
-    GLLog("glNormal3f") << nx << ny << nz;
-}
-
-void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) {
-    CALL_GL_API(glNormal3x, nx, ny, nz);
-    GLLog("glNormal3x") << GLLogFixed(nx) << GLLogFixed(ny) << GLLogFixed(nz);
-}
-
-void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glNormalPointer, type, stride, pointer);
-    GLLog("glNormalPointer") << GLLogEnum(type) << stride << pointer;
-}
-
-void API_ENTRY(glOrthof)(  GLfloat left, GLfloat right,
-                GLfloat bottom, GLfloat top,
-                GLfloat zNear, GLfloat zFar) {
-    CALL_GL_API(glOrthof, left, right, bottom, top, zNear, zFar);
-    GLLog("glOrthof") << left << right << bottom << top << zNear << zFar;
-}
-
-void API_ENTRY(glOrthox)(  GLfixed left, GLfixed right,
-                GLfixed bottom, GLfixed top,
-                GLfixed zNear, GLfixed zFar) {
-    CALL_GL_API(glOrthox, left, right, bottom, top, zNear, zFar);
-    GLLog("glOrthox") << GLLogFixed(left) << GLLogFixed(right)
-            << GLLogFixed(bottom) << GLLogFixed(top)
-            << GLLogFixed(zNear) << GLLogFixed(zFar);
-}
-
-void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
-    CALL_GL_API(glPixelStorei, pname, param);
-    GLLog("glPixelStorei") << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glPointSize)(GLfloat size) {
-    CALL_GL_API(glPointSize, size);
-    GLLog("glPointSize") << size;
-}
-
-void API_ENTRY(glPointSizex)(GLfixed size) {
-    CALL_GL_API(glPointSizex, size);
-    GLLog("glPointSizex") << GLLogFixed(size);
-}
-
-void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
-    CALL_GL_API(glPolygonOffset, factor, units);
-    GLLog("glPolygonOffset") << factor << units;
-}
-
-void API_ENTRY(glPolygonOffsetx)(GLfixed factor, GLfixed units) {
-    CALL_GL_API(glPolygonOffsetx, factor, units);
-    GLLog("glPolygonOffsetx") << GLLogFixed(factor) << GLLogFixed(units);
-}
-
-void API_ENTRY(glPopMatrix)(void) {
-    CALL_GL_API(glPopMatrix);
-    GLLog("glPopMatrix");
-}
-
-void API_ENTRY(glPushMatrix)(void) {
-    CALL_GL_API(glPushMatrix);
-    GLLog("glPushMatrix");
-}
-
-void API_ENTRY(glReadPixels)(  GLint x, GLint y, GLsizei width, GLsizei height,
-                    GLenum format, GLenum type, GLvoid *pixels) {
-    CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glReadPixels") << x << y << width << height << GLLogEnum(format) << GLLogEnum(type)
-            << GLLogBuffer<unsigned char>(static_cast<unsigned char *>(pixels));
-}
-
-void API_ENTRY(glRotatef)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glRotatef, angle, x, y, z);
-    GLLog("glRotatef") << angle << x << y << z;
-}
-
-void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glRotatex, angle, x, y, z);
-    GLLog("glRotatex") << GLLogFixed(angle) << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z);
-}
-
-void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
-    CALL_GL_API(glSampleCoverage, value, invert);
-    GLLog("glSampleCoverage") << value << GLLogBool(invert);
-}
-
-void API_ENTRY(glSampleCoveragex)(GLclampx value, GLboolean invert) {
-    CALL_GL_API(glSampleCoveragex, value, invert);
-    GLLog("glSampleCoveragex") << GLLogFixed(value) << GLLogBool(invert);
-}
-
-void API_ENTRY(glScalef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glScalef, x, y, z);
-    GLLog("glScalef") << x << y << z;
-}
-
-void API_ENTRY(glScalex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glScalex, x, y, z);
-    GLLog("glScalex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z);
-}
-
-void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glScissor, x, y, width, height);
-    GLLog("glScissor") << x << y << width << height;
-}
-
-void API_ENTRY(glShadeModel)(GLenum mode) {
-    CALL_GL_API(glShadeModel, mode);
-    GLLog("glShadeModel") << GLLogEnum(mode);
-}
-
-void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
-    CALL_GL_API(glStencilFunc, func, ref, mask);
-    GLLog("glStencilFunc") << GLLogEnum(func) << ref << mask;
-}
-
-void API_ENTRY(glStencilMask)(GLuint mask) {
-    CALL_GL_API(glStencilMask, mask);
-    GLLog("glStencilMask") << mask;
-}
-
-void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
-    CALL_GL_API(glStencilOp, fail, zfail, zpass);
-    GLLog("glStencilOp") << GLLogEnum(fail) << GLLogEnum(zfail) << GLLogEnum(zpass);
-}
-
-void API_ENTRY(glTexCoordPointer)( GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glTexCoordPointer, size, type, stride, pointer);
-    GLLog("glTexCoordPointer") << size << GLLogEnum(type) << stride << pointer;
-}
-
-void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) {
-    CALL_GL_API(glTexEnvf, target, pname, param);
-    GLLog("glTexEnvf") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexEnvfv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexEnvx, target, pname, param);
-    GLLog("glTexEnvx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glTexEnvxv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexEnvxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-
-void API_ENTRY(glTexImage2D)(  GLenum target, GLint level, GLint internalformat,
-                    GLsizei width, GLsizei height, GLint border, GLenum format,
-                    GLenum type, const GLvoid *pixels) {
-    CALL_GL_API(glTexImage2D, target, level, internalformat, width, height,
-            border, format, type, pixels);
-    GLLog("glTexImage2D") << GLLogEnum(target) << level << GLLogEnum(internalformat)
-            << width << height << border << GLLogEnum(format) << GLLogEnum(type)
-            << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels));
-}
-
-void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
-    CALL_GL_API(glTexParameterf, target, pname, param);
-    GLLog("glTexParameterf") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-
-void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) {
-    CALL_GL_API(glTexParameterx, target, pname, param);
-    GLLog("glTexParameterx") << GLLogEnum(target) << GLLogEnum(pname) << GLLogFixed(param);
-}
-
-void API_ENTRY(glTexSubImage2D)(   GLenum target, GLint level, GLint xoffset,
-                        GLint yoffset, GLsizei width, GLsizei height,
-                        GLenum format, GLenum type, const GLvoid *pixels) {
-    CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset,
-            width, height, format, type, pixels);
-    GLLog("glTexSubImage2D") << GLLogEnum(target) << level << xoffset << yoffset
-            << width << height << GLLogEnum(format) << GLLogEnum(type)
-            << GLLogBuffer<unsigned char>( static_cast<const unsigned char *>(pixels));
-}
-
-void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) {
-    CALL_GL_API(glTranslatef, x, y, z);
-    GLLog("glTranslatef") << x << y << z;
-}
-
-void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) {
-    CALL_GL_API(glTranslatex, x, y, z);
-    GLLog("glTranslatex") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z);
-}
-
-void API_ENTRY(glVertexPointer)(   GLint size, GLenum type,
-                        GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glVertexPointer, size, type, stride, pointer);
-    GLLog("glVertexPointer") << size << GLLogEnum(type) << stride << pointer;
-}
-
-void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
-    CALL_GL_API(glViewport, x, y, width, height);
-    GLLog("glViewport") << x << y << width << height;
-}
-
-// ES 1.1
-void API_ENTRY(glClipPlanef)(GLenum plane, const GLfloat *equation) {
-    CALL_GL_API(glClipPlanef, plane, equation);
-    GLLog("glClipPlanef") << GLLogEnum(plane) << GLLogBuffer<GLfloat>(equation, 4);
-}
-void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) {
-    CALL_GL_API(glClipPlanex, plane, equation);
-    GLLog("glClipPlanex") << GLLogEnum(plane) << GLLogBuffer<GLfixed>(equation, 4);
-}
-void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
-    CALL_GL_API(glBindBuffer, target, buffer);
-    GLLog("glBindBuffer") << GLLogEnum(target) << buffer;
-}
-void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
-    CALL_GL_API(glBufferData, target, size, data, usage);
-    GLLog("glBufferData") << GLLogEnum(target) << size
-        << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size);
-}
-void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
-    CALL_GL_API(glBufferSubData, target, offset, size, data);
-    GLLog("glBufferSubData") << GLLogEnum(target) << offset << size
-        << GLLogBuffer<unsigned char>(static_cast<const unsigned char*>(data), size);
-}
-void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) {
-    CALL_GL_API(glDeleteBuffers, n, buffers);
-    GLLog("glDeleteBuffers") << n << GLLogBuffer<GLuint>(buffers, n);
-}
-void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) {
-    CALL_GL_API(glGenBuffers, n, buffers);
-    GLLog("glGenBuffers") << n << GLLogBuffer<GLuint>(buffers, n);
-}
-void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *params) {
-    CALL_GL_API(glGetBooleanv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetBooleanv") << GLLogEnum(pname) << GLLogBuffer<GLboolean>(params);
-}
-void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetFixedv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetFixedv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetFloatv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetFloatv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
-    CALL_GL_API(glGetPointerv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetPointerv") << GLLogEnum(pname) << GLLogBuffer<void*>(params);
-}
-void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
-    // XXX: we need to compute the size of this buffer
-    CALL_GL_API(glGetBufferParameteriv, target, pname, params);
-    GLLog("glGetBufferParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-void API_ENTRY(glGetClipPlanef)(GLenum pname, GLfloat eqn[4]) {
-    CALL_GL_API(glGetClipPlanef, pname, eqn);
-    GLLog("glGetClipPlanef") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(eqn, 4);
-}
-void API_ENTRY(glGetClipPlanex)(GLenum pname, GLfixed eqn[4]) {
-    CALL_GL_API(glGetClipPlanex, pname, eqn);
-    GLLog("glGetClipPlanex") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(eqn, 4);
-}
-void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetLightxv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetLightxv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetLightfv, light, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetLightfv") << GLLogEnum(light) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetMaterialxv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetMaterialxv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetMaterialfv, face, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetMaterialfv") << GLLogEnum(face) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetTexEnvfv)(GLenum env, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetTexEnvfv, env, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexEnvfv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetTexEnviv)(GLenum env, GLenum pname, GLint *params) {
-    CALL_GL_API(glGetTexEnviv, env, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexEnviv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-void API_ENTRY(glGetTexEnvxv)(GLenum env, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetTexEnvxv, env, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexEnvxv") << GLLogEnum(env) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
-    CALL_GL_API(glGetTexParameterfv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) {
-    CALL_GL_API(glGetTexParameteriv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) {
-    CALL_GL_API(glGetTexParameterxv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glGetTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) {
-    GLLog("glIsBuffer") << buffer;
-    CALL_GL_API_RETURN(glIsBuffer, buffer);
-}
-GLboolean API_ENTRY(glIsEnabled)(GLenum cap) {
-    GLLog("glIsEnabled") << GLLogEnum(cap);
-    CALL_GL_API_RETURN(glIsEnabled, cap);
-}
-GLboolean API_ENTRY(glIsTexture)(GLuint texture) {
-    GLLog("glIsTexture") << texture;
-    CALL_GL_API_RETURN(glIsTexture, texture);
-}
-void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) {
-    CALL_GL_API(glPointParameterf, pname, param);
-    GLLog("glPointParameterf") << GLLogEnum(pname) << param;
-}
-void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glPointParameterfv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glPointParameterfv") << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) {
-    CALL_GL_API(glPointParameterx, pname, param);
-    GLLog("glPointParameterx") << GLLogEnum(pname) << GLLogFixed(param);
-}
-void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glPointParameterxv, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glPointParameterxv") << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
-    CALL_GL_API(glColor4ub, red, green, blue, alpha);
-    GLLog("glColor4ub") << red << green << blue << alpha;
-}
-void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) {
-    CALL_GL_API(glTexEnvi, target, pname, param);
-    GLLog("glTexEnvi") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) {
-    CALL_GL_API(glTexEnviv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexEnviv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-
-void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
-    CALL_GL_API(glTexParameterfv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexParameterfv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfloat>(params);
-}
-
-void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
-    CALL_GL_API(glTexParameteriv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexParameteriv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLint>(params);
-}
-
-void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
-    CALL_GL_API(glTexParameteri, target, pname, param);
-    GLLog("glTexParameteri") << GLLogEnum(target) << GLLogEnum(pname) << param;
-}
-void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) {
-    CALL_GL_API(glTexParameterxv, target, pname, params);
-    // XXX: we need to compute the size of this buffer
-    GLLog("glTexParameterxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params);
-}
-void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const GLvoid *pointer) {
-    CALL_GL_API(glPointSizePointerOES, type, stride, pointer);
-    GLLog("glPointSizePointerOES") << GLLogEnum(type) << stride << pointer;
-}
-
-// Extensions
-void API_ENTRY(glDrawTexsOES)(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) {
-    CALL_GL_API(glDrawTexsOES, x, y, z, w, h);
-    GLLog("glDrawTexsOES") << x << y << z << w << h;
-}
-void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint w, GLint h) {
-    CALL_GL_API(glDrawTexiOES, x, y, z, w, h);
-    GLLog("glDrawTexiOES") << x << y << z << w << h;
-}
-void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h) {
-    CALL_GL_API(glDrawTexfOES, x, y, z, w, h);
-    GLLog("glDrawTexfOES") << x << y << z << w << h;
-}
-void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) {
-    CALL_GL_API(glDrawTexxOES, x, y, z, w, h);
-    GLLog("glDrawTexfOES") << GLLogFixed(x) << GLLogFixed(y) << GLLogFixed(z) << GLLogFixed(w) << GLLogFixed(h);
-}
-void API_ENTRY(glDrawTexsvOES)(const GLshort* coords) {
-    CALL_GL_API(glDrawTexsvOES, coords);
-    GLLog("glDrawTexsvOES") << GLLogBuffer<GLshort>(coords, 5);
-}
-void API_ENTRY(glDrawTexivOES)(const GLint* coords) {
-    CALL_GL_API(glDrawTexivOES, coords);
-    GLLog("glDrawTexivOES") << GLLogBuffer<GLint>(coords, 5);
-}
-void API_ENTRY(glDrawTexfvOES)(const GLfloat* coords) {
-    CALL_GL_API(glDrawTexfvOES, coords);
-    GLLog("glDrawTexfvOES") << GLLogBuffer<GLfloat>(coords, 5);
-}
-void API_ENTRY(glDrawTexxvOES)(const GLfixed* coords) {
-    CALL_GL_API(glDrawTexxvOES, coords);
-    GLLog("glDrawTexxvOES") << GLLogBuffer<GLfixed>(coords, 5);
-}
-GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) {
-    GLLog("glQueryMatrixxOES") << GLLogBuffer<GLfixed>(mantissa, 16) << GLLogBuffer<GLfixed>(exponent, 16);
-    CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent);
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/opengl/libs/GLES_CM/glext_api.in b/opengl/libs/GLES_CM/glext_api.in
new file mode 100644
index 0000000..2c8648e
--- /dev/null
+++ b/opengl/libs/GLES_CM/glext_api.in
@@ -0,0 +1,270 @@
+void API_ENTRY(glBlendEquationSeparateOES)(GLenum modeRGB, GLenum modeAlpha) {
+    CALL_GL_API(glBlendEquationSeparateOES, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFuncSeparateOES)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    CALL_GL_API(glBlendFuncSeparateOES, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glBlendEquationOES)(GLenum mode) {
+    CALL_GL_API(glBlendEquationOES, mode);
+}
+void API_ENTRY(glDrawTexsOES)(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) {
+    CALL_GL_API(glDrawTexsOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexiOES)(GLint x, GLint y, GLint z, GLint width, GLint height) {
+    CALL_GL_API(glDrawTexiOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) {
+    CALL_GL_API(glDrawTexxOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexsvOES)(const GLshort *coords) {
+    CALL_GL_API(glDrawTexsvOES, coords);
+}
+void API_ENTRY(glDrawTexivOES)(const GLint *coords) {
+    CALL_GL_API(glDrawTexivOES, coords);
+}
+void API_ENTRY(glDrawTexxvOES)(const GLfixed *coords) {
+    CALL_GL_API(glDrawTexxvOES, coords);
+}
+void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) {
+    CALL_GL_API(glDrawTexfOES, x, y, z, width, height);
+}
+void API_ENTRY(glDrawTexfvOES)(const GLfloat *coords) {
+    CALL_GL_API(glDrawTexfvOES, coords);
+}
+void API_ENTRY(__glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) {
+    CALL_GL_API(glEGLImageTargetTexture2DOES, target, image);
+}
+void API_ENTRY(__glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) {
+    CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image);
+}
+void API_ENTRY(glAlphaFuncxOES)(GLenum func, GLclampx ref) {
+    CALL_GL_API(glAlphaFuncxOES, func, ref);
+}
+void API_ENTRY(glClearColorxOES)(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) {
+    CALL_GL_API(glClearColorxOES, red, green, blue, alpha);
+}
+void API_ENTRY(glClearDepthxOES)(GLclampx depth) {
+    CALL_GL_API(glClearDepthxOES, depth);
+}
+void API_ENTRY(glClipPlanexOES)(GLenum plane, const GLfixed *equation) {
+    CALL_GL_API(glClipPlanexOES, plane, equation);
+}
+void API_ENTRY(glColor4xOES)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
+    CALL_GL_API(glColor4xOES, red, green, blue, alpha);
+}
+void API_ENTRY(glDepthRangexOES)(GLclampx zNear, GLclampx zFar) {
+    CALL_GL_API(glDepthRangexOES, zNear, zFar);
+}
+void API_ENTRY(glFogxOES)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glFogxOES, pname, param);
+}
+void API_ENTRY(glFogxvOES)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glFogxvOES, pname, params);
+}
+void API_ENTRY(glFrustumxOES)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glFrustumxOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glGetClipPlanexOES)(GLenum pname, GLfixed eqn[4]) {
+    CALL_GL_API(glGetClipPlanexOES, pname, eqn);
+}
+void API_ENTRY(glGetFixedvOES)(GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetFixedvOES, pname, params);
+}
+void API_ENTRY(glGetLightxvOES)(GLenum light, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetLightxvOES, light, pname, params);
+}
+void API_ENTRY(glGetMaterialxvOES)(GLenum face, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetMaterialxvOES, face, pname, params);
+}
+void API_ENTRY(glGetTexEnvxvOES)(GLenum env, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetTexEnvxvOES, env, pname, params);
+}
+void API_ENTRY(glGetTexParameterxvOES)(GLenum target, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetTexParameterxvOES, target, pname, params);
+}
+void API_ENTRY(glLightModelxOES)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightModelxOES, pname, param);
+}
+void API_ENTRY(glLightModelxvOES)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightModelxvOES, pname, params);
+}
+void API_ENTRY(glLightxOES)(GLenum light, GLenum pname, GLfixed param) {
+    CALL_GL_API(glLightxOES, light, pname, param);
+}
+void API_ENTRY(glLightxvOES)(GLenum light, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glLightxvOES, light, pname, params);
+}
+void API_ENTRY(glLineWidthxOES)(GLfixed width) {
+    CALL_GL_API(glLineWidthxOES, width);
+}
+void API_ENTRY(glLoadMatrixxOES)(const GLfixed *m) {
+    CALL_GL_API(glLoadMatrixxOES, m);
+}
+void API_ENTRY(glMaterialxOES)(GLenum face, GLenum pname, GLfixed param) {
+    CALL_GL_API(glMaterialxOES, face, pname, param);
+}
+void API_ENTRY(glMaterialxvOES)(GLenum face, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glMaterialxvOES, face, pname, params);
+}
+void API_ENTRY(glMultMatrixxOES)(const GLfixed *m) {
+    CALL_GL_API(glMultMatrixxOES, m);
+}
+void API_ENTRY(glMultiTexCoord4xOES)(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
+    CALL_GL_API(glMultiTexCoord4xOES, target, s, t, r, q);
+}
+void API_ENTRY(glNormal3xOES)(GLfixed nx, GLfixed ny, GLfixed nz) {
+    CALL_GL_API(glNormal3xOES, nx, ny, nz);
+}
+void API_ENTRY(glOrthoxOES)(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) {
+    CALL_GL_API(glOrthoxOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glPointParameterxOES)(GLenum pname, GLfixed param) {
+    CALL_GL_API(glPointParameterxOES, pname, param);
+}
+void API_ENTRY(glPointParameterxvOES)(GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glPointParameterxvOES, pname, params);
+}
+void API_ENTRY(glPointSizexOES)(GLfixed size) {
+    CALL_GL_API(glPointSizexOES, size);
+}
+void API_ENTRY(glPolygonOffsetxOES)(GLfixed factor, GLfixed units) {
+    CALL_GL_API(glPolygonOffsetxOES, factor, units);
+}
+void API_ENTRY(glRotatexOES)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glRotatexOES, angle, x, y, z);
+}
+void API_ENTRY(glSampleCoveragexOES)(GLclampx value, GLboolean invert) {
+    CALL_GL_API(glSampleCoveragexOES, value, invert);
+}
+void API_ENTRY(glScalexOES)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glScalexOES, x, y, z);
+}
+void API_ENTRY(glTexEnvxOES)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexEnvxOES, target, pname, param);
+}
+void API_ENTRY(glTexEnvxvOES)(GLenum target, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexEnvxvOES, target, pname, params);
+}
+void API_ENTRY(glTexParameterxOES)(GLenum target, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexParameterxOES, target, pname, param);
+}
+void API_ENTRY(glTexParameterxvOES)(GLenum target, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexParameterxvOES, target, pname, params);
+}
+void API_ENTRY(glTranslatexOES)(GLfixed x, GLfixed y, GLfixed z) {
+    CALL_GL_API(glTranslatexOES, x, y, z);
+}
+GLboolean API_ENTRY(glIsRenderbufferOES)(GLuint renderbuffer) {
+    CALL_GL_API_RETURN(glIsRenderbufferOES, renderbuffer);
+}
+void API_ENTRY(glBindRenderbufferOES)(GLenum target, GLuint renderbuffer) {
+    CALL_GL_API(glBindRenderbufferOES, target, renderbuffer);
+}
+void API_ENTRY(glDeleteRenderbuffersOES)(GLsizei n, const GLuint* renderbuffers) {
+    CALL_GL_API(glDeleteRenderbuffersOES, n, renderbuffers);
+}
+void API_ENTRY(glGenRenderbuffersOES)(GLsizei n, GLuint* renderbuffers) {
+    CALL_GL_API(glGenRenderbuffersOES, n, renderbuffers);
+}
+void API_ENTRY(glRenderbufferStorageOES)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+    CALL_GL_API(glRenderbufferStorageOES, target, internalformat, width, height);
+}
+void API_ENTRY(glGetRenderbufferParameterivOES)(GLenum target, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetRenderbufferParameterivOES, target, pname, params);
+}
+GLboolean API_ENTRY(glIsFramebufferOES)(GLuint framebuffer) {
+    CALL_GL_API_RETURN(glIsFramebufferOES, framebuffer);
+}
+void API_ENTRY(glBindFramebufferOES)(GLenum target, GLuint framebuffer) {
+    CALL_GL_API(glBindFramebufferOES, target, framebuffer);
+}
+void API_ENTRY(glDeleteFramebuffersOES)(GLsizei n, const GLuint* framebuffers) {
+    CALL_GL_API(glDeleteFramebuffersOES, n, framebuffers);
+}
+void API_ENTRY(glGenFramebuffersOES)(GLsizei n, GLuint* framebuffers) {
+    CALL_GL_API(glGenFramebuffersOES, n, framebuffers);
+}
+GLenum API_ENTRY(glCheckFramebufferStatusOES)(GLenum target) {
+    CALL_GL_API_RETURN(glCheckFramebufferStatusOES, target);
+}
+void API_ENTRY(glFramebufferRenderbufferOES)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+    CALL_GL_API(glFramebufferRenderbufferOES, target, attachment, renderbuffertarget, renderbuffer);
+}
+void API_ENTRY(glFramebufferTexture2DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+    CALL_GL_API(glFramebufferTexture2DOES, target, attachment, textarget, texture, level);
+}
+void API_ENTRY(glGetFramebufferAttachmentParameterivOES)(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+    CALL_GL_API(glGetFramebufferAttachmentParameterivOES, target, attachment, pname, params);
+}
+void API_ENTRY(glGenerateMipmapOES)(GLenum target) {
+    CALL_GL_API(glGenerateMipmapOES, target);
+}
+void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
+    CALL_GL_API_RETURN(glMapBufferOES, target, access);
+}
+GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
+    CALL_GL_API_RETURN(glUnmapBufferOES, target);
+}
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void** params) {
+    CALL_GL_API(glGetBufferPointervOES, target, pname, params);
+}
+void API_ENTRY(glCurrentPaletteMatrixOES)(GLuint matrixpaletteindex) {
+    CALL_GL_API(glCurrentPaletteMatrixOES, matrixpaletteindex);
+}
+void API_ENTRY(glLoadPaletteFromModelViewMatrixOES)(void) {
+    CALL_GL_API(glLoadPaletteFromModelViewMatrixOES);
+}
+void API_ENTRY(glMatrixIndexPointerOES)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glMatrixIndexPointerOES, size, type, stride, pointer);
+}
+void API_ENTRY(glWeightPointerOES)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
+    CALL_GL_API(glWeightPointerOES, size, type, stride, pointer);
+}
+GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed mantissa[16], GLint exponent[16]) {
+    CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent);
+}
+void API_ENTRY(glDepthRangefOES)(GLclampf zNear, GLclampf zFar) {
+    CALL_GL_API(glDepthRangefOES, zNear, zFar);
+}
+void API_ENTRY(glFrustumfOES)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glFrustumfOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glOrthofOES)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) {
+    CALL_GL_API(glOrthofOES, left, right, bottom, top, zNear, zFar);
+}
+void API_ENTRY(glClipPlanefOES)(GLenum plane, const GLfloat *equation) {
+    CALL_GL_API(glClipPlanefOES, plane, equation);
+}
+void API_ENTRY(glGetClipPlanefOES)(GLenum pname, GLfloat eqn[4]) {
+    CALL_GL_API(glGetClipPlanefOES, pname, eqn);
+}
+void API_ENTRY(glClearDepthfOES)(GLclampf depth) {
+    CALL_GL_API(glClearDepthfOES, depth);
+}
+void API_ENTRY(glTexGenfOES)(GLenum coord, GLenum pname, GLfloat param) {
+    CALL_GL_API(glTexGenfOES, coord, pname, param);
+}
+void API_ENTRY(glTexGenfvOES)(GLenum coord, GLenum pname, const GLfloat *params) {
+    CALL_GL_API(glTexGenfvOES, coord, pname, params);
+}
+void API_ENTRY(glTexGeniOES)(GLenum coord, GLenum pname, GLint param) {
+    CALL_GL_API(glTexGeniOES, coord, pname, param);
+}
+void API_ENTRY(glTexGenivOES)(GLenum coord, GLenum pname, const GLint *params) {
+    CALL_GL_API(glTexGenivOES, coord, pname, params);
+}
+void API_ENTRY(glTexGenxOES)(GLenum coord, GLenum pname, GLfixed param) {
+    CALL_GL_API(glTexGenxOES, coord, pname, param);
+}
+void API_ENTRY(glTexGenxvOES)(GLenum coord, GLenum pname, const GLfixed *params) {
+    CALL_GL_API(glTexGenxvOES, coord, pname, params);
+}
+void API_ENTRY(glGetTexGenfvOES)(GLenum coord, GLenum pname, GLfloat *params) {
+    CALL_GL_API(glGetTexGenfvOES, coord, pname, params);
+}
+void API_ENTRY(glGetTexGenivOES)(GLenum coord, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetTexGenivOES, coord, pname, params);
+}
+void API_ENTRY(glGetTexGenxvOES)(GLenum coord, GLenum pname, GLfixed *params) {
+    CALL_GL_API(glGetTexGenxvOES, coord, pname, params);
+}
diff --git a/opengl/libs/egl_entries.in b/opengl/libs/egl_entries.in
index 33b4c65..3b4551b 100644
--- a/opengl/libs/egl_entries.in
+++ b/opengl/libs/egl_entries.in
@@ -43,3 +43,10 @@
 /* EGL 1.3 */
 
 /* EGL 1.4 */
+
+/* EGL_EGLEXT_VERSION 3 */
+
+EGL_ENTRY(EGLBoolean,  eglLockSurfaceKHR,   EGLDisplay, EGLSurface, const EGLint *)
+EGL_ENTRY(EGLBoolean,  eglUnlockSurfaceKHR, EGLDisplay, EGLSurface)
+EGL_ENTRY(EGLImageKHR, eglCreateImageKHR,   EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *)
+EGL_ENTRY(EGLBoolean,  eglDestroyImageKHR,  EGLDisplay, EGLImageKHR)
diff --git a/opengl/libs/gl_entries.in b/opengl/libs/gl_entries.in
index b97e8fe..d7cc5da 100644
--- a/opengl/libs/gl_entries.in
+++ b/opengl/libs/gl_entries.in
@@ -1,159 +1,145 @@
-GL_ENTRY(void, glColor4f, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glColor4x, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glNormal3f, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glNormal3x, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glCullFace, GLenum)
-GL_ENTRY(void, glFrontFace, GLenum)
-GL_ENTRY(void, glDisable, GLenum)
-GL_ENTRY(void, glEnable, GLenum)
-GL_ENTRY(void, glFinish, void)
-GL_ENTRY(void, glFlush, void)
-GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(const GLubyte*, glGetString, GLenum)
-GL_ENTRY(void, glGetIntegerv, GLenum, GLint *)
-GL_ENTRY(void, glColorMask, GLboolean, GLboolean, GLboolean, GLboolean)
-GL_ENTRY(void, glDepthMask, GLboolean)
-GL_ENTRY(void, glStencilMask, GLuint)
-GL_ENTRY(void, glDepthFunc, GLenum)
-GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
-GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
-GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
-GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
-GL_ENTRY(void, glLogicOp, GLenum opcode)
-GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
 GL_ENTRY(void, glAlphaFunc, GLenum func, GLclampf ref)
-GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
-GL_ENTRY(void, glClear, GLbitfield mask)
-GL_ENTRY(void, glClearColor, GLclampf r, GLclampf g, GLclampf b, GLclampf a)
-GL_ENTRY(void, glClearColorx, GLclampx r, GLclampx g, GLclampx b, GLclampx a)
+GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
 GL_ENTRY(void, glClearDepthf, GLclampf depth)
+GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glFrustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
+GL_ENTRY(void, glOrthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glPointSize, GLfloat size)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColorx, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
 GL_ENTRY(void, glClearDepthx, GLclampx depth)
 GL_ENTRY(void, glClearStencil, GLint s)
-GL_ENTRY(void, glPointSize, GLfloat)
-GL_ENTRY(void, glPointSizex, GLfixed)
-GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
-GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
-GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
-GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
-GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glHint, GLenum, GLenum mode)
-GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glClientActiveTexture, GLenum texture)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangex, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableClientState, GLenum array)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableClientState, GLenum array)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glFrustumx, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetTexEnviv, GLenum env, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
 GL_ENTRY(void, glLineWidthx, GLfixed width)
-GL_ENTRY(void, glShadeModel, GLenum)
-GL_ENTRY(void, glLightModelf, GLenum, GLfloat)
-GL_ENTRY(void, glLightModelfv, GLenum, const GLfloat *)
-GL_ENTRY(void, glLightModelx, GLenum, GLfixed)
-GL_ENTRY(void, glLightModelxv, GLenum, const GLfixed *)
-GL_ENTRY(void, glLightf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glLightfv, GLenum, GLenum, const GLfloat *)
-GL_ENTRY(void, glLightx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glLightxv, GLenum, GLenum, const GLfixed *)
-GL_ENTRY(void, glMaterialf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glMaterialfv, GLenum, GLenum, const GLfloat *)
-GL_ENTRY(void, glMaterialx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glMaterialxv, GLenum, GLenum, const GLfixed *)
-GL_ENTRY(void, glFogf, GLenum, GLfloat)
-GL_ENTRY(void, glFogfv, GLenum, const GLfloat *)
-GL_ENTRY(void, glFogx, GLenum, GLfixed)
-GL_ENTRY(void, glFogxv, GLenum, const GLfixed *)
-GL_ENTRY(void, glVertexPointer, GLint, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glColorPointer, GLint, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glNormalPointer, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glTexCoordPointer, GLint, GLenum, GLsizei, const GLvoid *)
-GL_ENTRY(void, glEnableClientState, GLenum)
-GL_ENTRY(void, glDisableClientState, GLenum)
-GL_ENTRY(void, glClientActiveTexture, GLenum)
-GL_ENTRY(void, glDrawArrays, GLenum, GLint first, GLsizei)
-GL_ENTRY(void, glDrawElements, GLenum, GLsizei, GLenum, const GLvoid *)
 GL_ENTRY(void, glLoadIdentity, void)
-GL_ENTRY(void, glLoadMatrixf, const GLfloat*)
-GL_ENTRY(void, glLoadMatrixx, const GLfixed*)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *params)
 GL_ENTRY(void, glMatrixMode, GLenum mode)
-GL_ENTRY(void, glMultMatrixf, const GLfloat*)
-GL_ENTRY(void, glMultMatrixx, const GLfixed*)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glOrthox, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSizex, GLfixed size)
+GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
 GL_ENTRY(void, glPopMatrix, void)
 GL_ENTRY(void, glPushMatrix, void)
-GL_ENTRY(void, glFrustumf, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glFrustumx, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glOrthof, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glOrthox, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glRotatef, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glRotatex, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glScalef, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glScalex, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glTranslatef, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glTranslatex, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glViewport, GLint, GLint, GLsizei, GLsizei)
-GL_ENTRY(void, glActiveTexture, GLenum)
-GL_ENTRY(void, glBindTexture, GLenum, GLuint)
-GL_ENTRY(void, glGenTextures, GLsizei, GLuint*)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *)
-GL_ENTRY(void, glMultiTexCoord4f, GLenum, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glMultiTexCoord4x, GLenum, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glPixelStorei, GLenum, GLint)
-GL_ENTRY(void, glTexEnvf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glTexEnvfv, GLenum, GLenum, const GLfloat*)
-GL_ENTRY(void, glTexEnvx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glTexEnvxv, GLenum, GLenum, const GLfixed*)
-GL_ENTRY(void, glTexParameterf, GLenum, GLenum, GLfloat)
-GL_ENTRY(void, glTexParameterx, GLenum, GLenum, GLfixed)
-GL_ENTRY(void, glCompressedTexImage2D,    GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)
-GL_ENTRY(void, glCopyTexImage2D, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint)
-GL_ENTRY(void, glCopyTexSubImage2D, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)
-GL_ENTRY(void, glTexImage2D, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)
-GL_ENTRY(void, glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*)
-GL_ENTRY(void, glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *)
-
-// 1.1 additions
-GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat*)
-GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed*)
-GL_ENTRY(void, glBindBuffer, GLenum, GLuint)
-GL_ENTRY(void, glBufferData, GLenum, GLsizeiptr, const GLvoid*, GLenum)
-GL_ENTRY(void, glBufferSubData, GLenum, GLintptr, GLsizeiptr, const GLvoid*)
-GL_ENTRY(void, glDeleteBuffers, GLsizei, const GLuint*)
-GL_ENTRY(void, glGenBuffers, GLsizei, GLuint*)
-GL_ENTRY(void, glGetBooleanv, GLenum, GLboolean *)
-GL_ENTRY(void, glGetFixedv, GLenum, GLfixed *)
-GL_ENTRY(void, glGetFloatv, GLenum, GLfloat *)
-GL_ENTRY(void, glGetPointerv, GLenum, void **)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum, GLenum, GLint *)
-GL_ENTRY(void, glGetClipPlanef, GLenum, GLfloat[4])
-GL_ENTRY(void, glGetClipPlanex, GLenum, GLfixed[4])
-GL_ENTRY(void, glGetLightxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(void, glGetLightfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetMaterialxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(void, glGetMaterialfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetTexEnvfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetTexEnviv, GLenum, GLenum, GLint *)
-GL_ENTRY(void, glGetTexEnvxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(void, glGetTexParameterfv, GLenum, GLenum, GLfloat *)
-GL_ENTRY(void, glGetTexParameteriv, GLenum, GLenum, GLint *)
-GL_ENTRY(void, glGetTexParameterxv, GLenum, GLenum, GLfixed *)
-GL_ENTRY(GLboolean, glIsBuffer, GLuint)
-GL_ENTRY(GLboolean, glIsEnabled, GLenum)
-GL_ENTRY(GLboolean, glIsTexture, GLuint)
-GL_ENTRY(void, glPointParameterf, GLenum, GLfloat)
-GL_ENTRY(void, glPointParameterfv, GLenum, const GLfloat *)
-GL_ENTRY(void, glPointParameterx, GLenum, GLfixed)
-GL_ENTRY(void, glPointParameterxv, GLenum, const GLfixed *)
-GL_ENTRY(void, glColor4ub, GLubyte, GLubyte, GLubyte, GLubyte)
-GL_ENTRY(void, glTexEnvi, GLenum, GLenum, GLint)
-GL_ENTRY(void, glTexEnviv, GLenum, GLenum, const GLint *)
-GL_ENTRY(void, glTexParameterfv, GLenum, GLenum, const GLfloat *)
-GL_ENTRY(void, glTexParameteriv, GLenum, GLenum, const GLint *)
-GL_ENTRY(void, glTexParameteri, GLenum, GLenum, GLint)
-GL_ENTRY(void, glTexParameterxv, GLenum, GLenum, const GLfixed *)
-GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid*)
-
-// Extensions
-GL_ENTRY(void, glDrawTexsOES, GLshort, GLshort, GLshort, GLshort, GLshort)
-GL_ENTRY(void, glDrawTexiOES, GLint, GLint, GLint, GLint, GLint)
-GL_ENTRY(void, glDrawTexfOES, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)
-GL_ENTRY(void, glDrawTexxOES, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)
-GL_ENTRY(void, glDrawTexsvOES, const GLshort*)
-GL_ENTRY(void, glDrawTexivOES, const GLint*)
-GL_ENTRY(void, glDrawTexfvOES, const GLfloat*)
-GL_ENTRY(void, glDrawTexxvOES, const GLfixed*)
-GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed* mantissa, GLint* exponent)
-
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
+GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glShadeModel, GLenum mode)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/libs/gl_logger.h b/opengl/libs/gl_logger.h
deleted file mode 100644
index ce85dd1..0000000
--- a/opengl/libs/gl_logger.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* 
- ** Copyright 2007, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License"); 
- ** you may not use this file except in compliance with the License. 
- ** You may obtain a copy of the License at 
- **
- **     http://www.apache.org/licenses/LICENSE-2.0 
- **
- ** Unless required by applicable law or agreed to in writing, software 
- ** distributed under the License is distributed on an "AS IS" BASIS, 
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- ** See the License for the specific language governing permissions and 
- ** limitations under the License.
- */
-
-#ifndef ANDROID_GL_LOGGER_H
-#define ANDROID_GL_LOGGER_H
-
-namespace android {
-#define GL_ENTRY(r, api, ...) r log_##api(__VA_ARGS__);
-#include "gl_entries.in"
-#undef GL_ENTRY
-}; // namespace android
-
-#endif /* ANDROID_GL_LOGGER_H */
diff --git a/opengl/libs/glext_entries.in b/opengl/libs/glext_entries.in
new file mode 100644
index 0000000..dd09c71
--- /dev/null
+++ b/opengl/libs/glext_entries.in
@@ -0,0 +1,90 @@
+GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendEquationOES, GLenum mode)
+GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
+GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
+GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
+GL_ENTRY(void, glClearColorxOES, GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
+GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glDepthRangexOES, GLclampx zNear, GLclampx zFar)
+GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glFrustumxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum env, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLineWidthxOES, GLfixed width)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glOrthoxOES, GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar)
+GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
+GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
+GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
+GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint* framebuffers)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint* framebuffers)
+GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
+GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint* params)
+GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
+GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
+GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
+GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
+GL_ENTRY(void, glDepthRangefOES, GLclampf zNear, GLclampf zFar)
+GL_ENTRY(void, glFrustumfOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glOrthofOES, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
+GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
+GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 63fb017..fd97254 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -22,9 +22,10 @@
 #include <errno.h>
 
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 
-#define GL_LOGGER                   0
 #if !defined(__arm__)
 #define USE_SLOW_BINDING            1
 #else
@@ -35,7 +36,7 @@
 #define MAX_NUMBER_OF_GL_EXTENSIONS 32
 
 
-#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER && __OPTIMIZE__
+#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && __OPTIMIZE__
 #define USE_FAST_TLS_KEY            1
 #else
 #define USE_FAST_TLS_KEY            0
@@ -55,7 +56,10 @@
 enum {
     IMPL_HARDWARE = 0,
     IMPL_SOFTWARE,
-    IMPL_CONTEXT_LOST,
+    
+    IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
+
+    IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
     IMPL_NO_CONTEXT,
     
     IMPL_NUM_IMPLEMENTATIONS
@@ -73,6 +77,7 @@
 struct gl_hooks_t {
     struct gl_t {
         #include "gl_entries.in"
+        #include "glext_entries.in"
     } gl;
     struct egl_t {
         #include "egl_entries.in"
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
new file mode 100755
index 0000000..107768b
--- /dev/null
+++ b/opengl/libs/tools/genfiles
@@ -0,0 +1,20 @@
+#! /bin/sh
+#
+# Copyright (C) 2008 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.
+
+./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in 
+./glentrygen ../../include/GLES/gl.h > ../gl_entries.in 
+./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in 
+./glentrygen ../../include/GLES/glext.h > ../glext_entries.in 
diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen
new file mode 100755
index 0000000..a2c3a7b
--- /dev/null
+++ b/opengl/libs/tools/glapigen
@@ -0,0 +1,72 @@
+#! /usr/bin/perl
+#
+# Copyright (C) 2008 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.
+
+use strict;
+
+while (my $line = <>) {
+  next if $line =~ /^\//;
+  next if $line =~ /^#/;
+  next if $line =~ /^\s*$/;
+  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+    next;
+  }
+  my $type = $1;
+  my $name = $2;
+  my $args = $3;
+
+  #printf("%s", $line);
+  
+  my $prefix = "";
+  if ($name eq "glEGLImageTargetTexture2DOES") {
+    $prefix = "__";
+  }
+  if ($name eq "glEGLImageTargetRenderbufferStorageOES") {
+    $prefix = "__";
+  }
+  
+  printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args);
+  
+  printf(" {\n");
+  if ($type eq "void") {
+    printf("    CALL_GL_API(%s", $name);
+  } else {
+    printf("    CALL_GL_API_RETURN(%s", $name);
+  }
+  my @args = split ',', $args;
+  my $len = scalar(@args);
+  for (my $num = 0; $num < $len; $num++) {
+    if ($args[$num] ne "void") {
+      print ", ";
+      #
+      # extract the name from the parameter
+      # type name
+      # const type *name
+      # type *name
+      # type name[4]
+      #
+      if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) {
+        printf("%s", $2);
+      }
+    }
+  }
+  printf(");\n");
+  printf("}\n");
+}
+
+
+
+
+
diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen
new file mode 100755
index 0000000..5e0f7b6
--- /dev/null
+++ b/opengl/libs/tools/glentrygen
@@ -0,0 +1,31 @@
+#! /usr/bin/perl
+#
+# Copyright (C) 2008 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.
+
+use strict;
+
+while (my $line = <>) {
+  next if $line =~ /^\//;
+  next if $line =~ /^#/;
+  next if $line =~ /^\s*$/;
+  if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
+    next;
+  }
+  my $type = $1;
+  my $name = $2;
+  my $args = $3;
+
+  printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args);
+}
diff --git a/opengl/tools/glgen/.gitignore b/opengl/tools/glgen/.gitignore
new file mode 100644
index 0000000..007ec65
--- /dev/null
+++ b/opengl/tools/glgen/.gitignore
@@ -0,0 +1,2 @@
+generated
+out
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 1c49861..011a6ed 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -1,28 +1,58 @@
-#!/bin/sh
+#!/bin/bash
+set -u
+set -e
 rm -rf out generated
 
 mkdir out
 mkdir -p out/javax/microedition/khronos/opengles
 mkdir -p out/com/google/android/gles_jni
 mkdir -p out/android/graphics
+mkdir -p out/android/opengl
 
 echo "package android.graphics;" > out/android/graphics/Canvas.java
 echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
 
 GLFILE=out/javax/microedition/khronos/opengles/GL.java
-cp stubs/GLHeader.java-if $GLFILE
+cp stubs/jsr239/GLHeader.java-if $GLFILE
 
-GLGEN_FILES="CFunc.java CType.java CodeEmitter.java GenerateGL.java JFunc.java JType.java JniCodeEmitter.java ParameterChecker.java"
+GLGEN_FILES="CFunc.java CType.java CodeEmitter.java GenerateGL.java GenerateGLES.java GLESCodeEmitter.java JFunc.java JniCodeEmitter.java JType.java Jsr239CodeEmitter.java ParameterChecker.java"
 
 pushd src > /dev/null
 javac ${GLGEN_FILES}
+JAVAC_RESULT=$?
+if [ $JAVAC_RESULT -ne 0 ]; then
+    echo "Could not compile glgen."
+    exit $JAVAC_RESULT
+fi
 popd > /dev/null
-java -classpath src GenerateGL -c glspec-1.0 glspec-1.0ext glspec-1.1 glspec-1.1ext glspec-1.1extpack glspec-checks
+
+echo "Generating JSR239-like APIs"
+java -classpath src GenerateGL -c specs/jsr239/glspec-1.0 specs/jsr239/glspec-1.0ext specs/jsr239/glspec-1.1 specs/jsr239/glspec-1.1ext specs/jsr239/glspec-1.1extpack specs/jsr239/glspec-checks
+JAVA_RESULT=$?
+if [ $JAVA_RESULT -ne 0 ]; then
+    echo "Could not run GenerateGL."
+    exit $JAVA_RESULT
+fi
+
+echo "Generating static OpenGLES 1.1 bindings"
+java -classpath src GenerateGLES
+JAVA_RESULT=$?
+if [ $JAVA_RESULT -ne 0 ]; then
+    echo "Could not run GenerateGLES."
+    exit $JAVA_RESULT
+fi
+
+rm src/*.class
 
 pushd out > /dev/null
 mkdir classes
-javac -d classes com/google/android/gles_jni/GLImpl.java javax/microedition/khronos/opengles/GL10.java javax/microedition/khronos/opengles/GL10Ext.java javax/microedition/khronos/opengles/GL11.java javax/microedition/khronos/opengles/GL11Ext.java javax/microedition/khronos/opengles/GL11ExtensionPack.java
+javac -d classes com/google/android/gles_jni/GLImpl.java javax/microedition/khronos/opengles/GL10.java javax/microedition/khronos/opengles/GL10Ext.java javax/microedition/khronos/opengles/GL11.java javax/microedition/khronos/opengles/GL11Ext.java javax/microedition/khronos/opengles/GL11ExtensionPack.java android/opengl/GLES10.java android/opengl/GLES10Ext.java android/opengl/GLES11.java android/opengl/GLES11Ext.java
 popd > /dev/null
+JAVA_RESULT=$?
+if [ $JAVA_RESULT -ne 0 ]; then
+    echo "Could not compile generated classes."
+    exit $JAVA_RESULT
+fi
 
 rm -rf generated
 mkdir -p generated/C
@@ -30,70 +60,44 @@
 cp -r out/com generated
 cp -r out/javax generated
 
+cp out/android_opengl_*.cpp generated/C
+mkdir -p generated/android/opengl
+cp -r out/android/opengl generated/android
+
 rm -rf out
+KEEP_GENERATED=0
+SAID_PLEASE=0
 
-# com_google_android_gles_jni_GLImpl.cpp
-if cmp ../../../frameworks/base/core/jni/com_google_android_gles_jni_GLImpl.cpp generated/C/com_google_android_gles_jni_GLImpl.cpp ; then
-echo com_google_android_gles_jni_GLImpl.cpp unchanged
-else
-echo Please edit ../../../frameworks/base/core/jni/com_google_android_gles_jni_GLImpl.cpp
-echo Please cp generated/C/com_google_android_gles_jni_GLImpl.cpp ../../../frameworks/base/core/jni
+# compareGenerated destDir generatedDir file
+compareGenerated() {
+    if cmp -s $1/$3 $2/$3 ; then
+        echo "#    " $3 unchanged
+    else
+        if [ $SAID_PLEASE == "0" ] ; then
+            echo Please evaluate the following commands:
+            echo
+            SAID_PLEASE=1
+        fi
+        echo "    " cp $2/$3 $1
+        echo "    " git add $1/$3
+        KEEP_GENERATED=1
+    fi
+}
+
+compareGenerated ../../../core/jni generated/C com_google_android_gles_jni_GLImpl.cpp
+compareGenerated ../../java/com/google/android/gles_jni generated/com/google/android/gles_jni GLImpl.java
+
+for x in GL.java GL10.java GL10Ext.java GL11.java GL11Ext.java GL11ExtensionPack.java
+do
+    compareGenerated ../../java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x
+done
+
+for x in GLES10 GLES10Ext GLES11 GLES11Ext
+do
+    compareGenerated ../../java/android/opengl generated/android/opengl ${x}.java
+    compareGenerated ../../../core/jni generated/C android_opengl_${x}.cpp
+done
+
+if [ $KEEP_GENERATED == "0" ] ; then
+    rm -rf generated
 fi
-
-# GLImpl.java
-if cmp ../../java/com/google/android/gles_jni/GLImpl.java generated/com/google/android/gles_jni/GLImpl.java ; then
-echo GLImpl.java unchanged
-else
-echo Please edit ../../java/com/google/android/gles_jni/GLImpl.java
-echo Please cp generated/com/google/android/gles_jni/GLImpl.java ../../java/com/google/android/gles_jni
-fi
-
-# GL.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL.java generated/javax/microedition/khronos/opengles/GL.java ; then
-echo GL.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL.java ../../java/javax/microedition/khronos/opengles/GL.java
-fi
-
-# GL10.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL10.java generated/javax/microedition/khronos/opengles/GL10.java ; then
-echo GL10.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL10.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL10.java ../../java/javax/microedition/khronos/opengles/GL10.java
-fi
-
-# GL10Ext.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL10Ext.java generated/javax/microedition/khronos/opengles/GL10Ext.java ; then
-echo GL10Ext.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL10Ext.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL10Ext.java ../../java/javax/microedition/khronos/opengles/GL10Ext.java
-fi
-
-# GL11.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL11.java generated/javax/microedition/khronos/opengles/GL11.java ; then
-echo GL11.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL11.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL11.java ../../java/javax/microedition/khronos/opengles/GL11.java
-fi
-
-# GL11Ext.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL11Ext.java generated/javax/microedition/khronos/opengles/GL11Ext.java ; then
-echo GL11Ext.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL11Ext.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL11Ext.java ../../java/javax/microedition/khronos/opengles/GL11Ext.java
-fi
-
-# GL11ExtensionPack.java
-if cmp ../../java/javax/microedition/khronos/opengles/GL11ExtensionPack.java generated/javax/microedition/khronos/opengles/GL11ExtensionPack.java ; then
-echo GL11ExtensionPack.java unchanged
-else
-echo Please edit ../../java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
-echo Please cp generated/javax/microedition/khronos/opengles/GL11ExtensionPack.java ../../java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
-fi
-
-rm -rf generated
diff --git a/opengl/tools/glgen/specs/gles11/GLES10.spec b/opengl/tools/glgen/specs/gles11/GLES10.spec
new file mode 100644
index 0000000..8e1152d
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES10.spec
@@ -0,0 +1,106 @@
+void glActiveTexture ( GLenum texture )
+void glAlphaFunc ( GLenum func, GLclampf ref )
+void glAlphaFuncx ( GLenum func, GLclampx ref )
+void glBindTexture ( GLenum target, GLuint texture )
+void glBlendFunc ( GLenum sfactor, GLenum dfactor )
+void glClear ( GLbitfield mask )
+void glClearColor ( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+void glClearColorx ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha )
+void glClearDepthf ( GLclampf depth )
+void glClearDepthx ( GLclampx depth )
+void glClearStencil ( GLint s )
+void glClientActiveTexture ( GLenum texture )
+void glColor4f ( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+void glColor4x ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha )
+void glColorMask ( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha )
+void glColorPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data )
+void glCompressedTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data )
+void glCopyTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
+void glCopyTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height )
+void glCullFace ( GLenum mode )
+void glDeleteTextures ( GLsizei n, const GLuint *textures )
+void glDepthFunc ( GLenum func )
+void glDepthMask ( GLboolean flag )
+void glDepthRangef ( GLclampf zNear, GLclampf zFar )
+void glDepthRangex ( GLclampx zNear, GLclampx zFar )
+void glDisable ( GLenum cap )
+void glDisableClientState ( GLenum array )
+void glDrawArrays ( GLenum mode, GLint first, GLsizei count )
+void glDrawElements ( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
+void glEnable ( GLenum cap )
+void glEnableClientState ( GLenum array )
+void glFinish ( void )
+void glFlush ( void )
+void glFogf ( GLenum pname, GLfloat param )
+void glFogfv ( GLenum pname, const GLfloat *params )
+void glFogx ( GLenum pname, GLfixed param )
+void glFogxv ( GLenum pname, const GLfixed *params )
+void glFrontFace ( GLenum mode )
+void glFrustumf ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glFrustumx ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glGenTextures ( GLsizei n, GLuint *textures )
+GLenum glGetError ( void )
+void glGetIntegerv ( GLenum pname, GLint *params )
+const GLubyte * glGetString ( GLenum name )
+void glHint ( GLenum target, GLenum mode )
+void glLightModelf ( GLenum pname, GLfloat param )
+void glLightModelfv ( GLenum pname, const GLfloat *params )
+void glLightModelx ( GLenum pname, GLfixed param )
+void glLightModelxv ( GLenum pname, const GLfixed *params )
+void glLightf ( GLenum light, GLenum pname, GLfloat param )
+void glLightfv ( GLenum light, GLenum pname, const GLfloat *params )
+void glLightx ( GLenum light, GLenum pname, GLfixed param )
+void glLightxv ( GLenum light, GLenum pname, const GLfixed *params )
+void glLineWidth ( GLfloat width )
+void glLineWidthx ( GLfixed width )
+void glLoadIdentity ( void )
+void glLoadMatrixf ( const GLfloat *m )
+void glLoadMatrixx ( const GLfixed *m )
+void glLogicOp ( GLenum opcode )
+void glMaterialf ( GLenum face, GLenum pname, GLfloat param )
+void glMaterialfv ( GLenum face, GLenum pname, const GLfloat *params )
+void glMaterialx ( GLenum face, GLenum pname, GLfixed param )
+void glMaterialxv ( GLenum face, GLenum pname, const GLfixed *params )
+void glMatrixMode ( GLenum mode )
+void glMultMatrixf ( const GLfloat *m )
+void glMultMatrixx ( const GLfixed *m )
+void glMultiTexCoord4f ( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q )
+void glMultiTexCoord4x ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q )
+void glNormal3f ( GLfloat nx, GLfloat ny, GLfloat nz )
+void glNormal3x ( GLfixed nx, GLfixed ny, GLfixed nz )
+void glNormalPointer ( GLenum type, GLsizei stride, const GLvoid *pointer )
+void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glOrthox ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glPixelStorei ( GLenum pname, GLint param )
+void glPointSize ( GLfloat size )
+void glPointSizex ( GLfixed size )
+void glPolygonOffset ( GLfloat factor, GLfloat units )
+void glPolygonOffsetx ( GLfixed factor, GLfixed units )
+void glPopMatrix ( void )
+void glPushMatrix ( void )
+void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels )
+void glRotatef ( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
+void glRotatex ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z )
+void glSampleCoverage ( GLclampf value, GLboolean invert )
+void glSampleCoveragex ( GLclampx value, GLboolean invert )
+void glScalef ( GLfloat x, GLfloat y, GLfloat z )
+void glScalex ( GLfixed x, GLfixed y, GLfixed z )
+void glScissor ( GLint x, GLint y, GLsizei width, GLsizei height )
+void glShadeModel ( GLenum mode )
+void glStencilFunc ( GLenum func, GLint ref, GLuint mask )
+void glStencilMask ( GLuint mask )
+void glStencilOp ( GLenum fail, GLenum zfail, GLenum zpass )
+void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glTexEnvf ( GLenum target, GLenum pname, GLfloat param )
+void glTexEnvfv ( GLenum target, GLenum pname, const GLfloat *params )
+void glTexEnvx ( GLenum target, GLenum pname, GLfixed param )
+void glTexEnvxv ( GLenum target, GLenum pname, const GLfixed *params )
+void glTexImage2D ( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
+void glTexParameterf ( GLenum target, GLenum pname, GLfloat param )
+void glTexParameterx ( GLenum target, GLenum pname, GLfixed param )
+void glTexSubImage2D ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels )
+void glTranslatef ( GLfloat x, GLfloat y, GLfloat z )
+void glTranslatex ( GLfixed x, GLfixed y, GLfixed z )
+void glVertexPointer ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height )
diff --git a/opengl/tools/glgen/specs/gles11/GLES10Ext.spec b/opengl/tools/glgen/specs/gles11/GLES10Ext.spec
new file mode 100644
index 0000000..53f6c65
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES10Ext.spec
@@ -0,0 +1 @@
+GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent )
diff --git a/opengl/tools/glgen/specs/gles11/GLES11.spec b/opengl/tools/glgen/specs/gles11/GLES11.spec
new file mode 100644
index 0000000..5527c18
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES11.spec
@@ -0,0 +1,44 @@
+void glBindBuffer ( GLenum target, GLuint buffer )
+void glBufferData ( GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage )
+void glBufferSubData ( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data )
+void glClipPlanef ( GLenum plane, const GLfloat *equation )
+void glClipPlanex ( GLenum plane, const GLfixed *equation )
+void glColor4ub ( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
+void glColorPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
+void glDeleteBuffers ( GLsizei n, const GLuint *buffers )
+void glDrawElements ( GLenum mode, GLsizei count, GLenum type, GLint offset )
+void glGenBuffers ( GLsizei n, GLuint *buffers )
+void glGetBooleanv ( GLenum pname, GLboolean *params )
+void glGetBufferParameteriv ( GLenum target, GLenum pname, GLint *params )
+void glGetClipPlanef ( GLenum pname, GLfloat *eqn )
+void glGetClipPlanex ( GLenum pname, GLfixed *eqn )
+void glGetFixedv ( GLenum pname, GLfixed *params )
+void glGetFloatv ( GLenum pname, GLfloat *params )
+void glGetLightfv ( GLenum light, GLenum pname, GLfloat *params )
+void glGetLightxv ( GLenum light, GLenum pname, GLfixed *params )
+void glGetMaterialfv ( GLenum face, GLenum pname, GLfloat *params )
+void glGetMaterialxv ( GLenum face, GLenum pname, GLfixed *params )
+// void glGetPointerv ( GLenum pname, void **params )
+void glGetTexEnvfv ( GLenum env, GLenum pname, GLfloat *params )
+void glGetTexEnviv ( GLenum env, GLenum pname, GLint *params )
+void glGetTexEnvxv ( GLenum env, GLenum pname, GLfixed *params )
+void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params )
+void glGetTexParameteriv ( GLenum target, GLenum pname, GLint *params )
+void glGetTexParameterxv ( GLenum target, GLenum pname, GLfixed *params )
+GLboolean glIsBuffer ( GLuint buffer )
+GLboolean glIsEnabled ( GLenum cap )
+GLboolean glIsTexture ( GLuint texture )
+void glNormalPointer ( GLenum type, GLsizei stride, GLint offset )
+void glPointParameterf ( GLenum pname, GLfloat param )
+void glPointParameterfv ( GLenum pname, const GLfloat *params )
+void glPointParameterx ( GLenum pname, GLfixed param )
+void glPointParameterxv ( GLenum pname, const GLfixed *params )
+void glPointSizePointerOES ( GLenum type, GLsizei stride, const GLvoid *pointer )
+void glTexCoordPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
+void glTexEnvi ( GLenum target, GLenum pname, GLint param )
+void glTexEnviv ( GLenum target, GLenum pname, const GLint *params )
+void glTexParameterfv ( GLenum target, GLenum pname, const GLfloat *params )
+void glTexParameteri ( GLenum target, GLenum pname, GLint param )
+void glTexParameteriv ( GLenum target, GLenum pname, const GLint *params )
+void glTexParameterxv ( GLenum target, GLenum pname, const GLfixed *params )
+void glVertexPointer ( GLint size, GLenum type, GLsizei stride, GLint offset )
diff --git a/opengl/tools/glgen/specs/gles11/GLES11Ext.spec b/opengl/tools/glgen/specs/gles11/GLES11Ext.spec
new file mode 100644
index 0000000..cd7333a
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES11Ext.spec
@@ -0,0 +1,90 @@
+void glBlendEquationSeparateOES ( GLenum modeRGB, GLenum modeAlpha )
+void glBlendFuncSeparateOES ( GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha )
+void glBlendEquationOES ( GLenum mode )
+void glDrawTexsOES ( GLshort x, GLshort y, GLshort z, GLshort width, GLshort height )
+void glDrawTexiOES ( GLint x, GLint y, GLint z, GLint width, GLint height )
+void glDrawTexxOES ( GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height )
+void glDrawTexsvOES ( const GLshort *coords )
+void glDrawTexivOES ( const GLint *coords )
+void glDrawTexxvOES ( const GLfixed *coords )
+void glDrawTexfOES ( GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height )
+void glDrawTexfvOES ( const GLfloat *coords )
+void glEGLImageTargetTexture2DOES ( GLenum target, GLeglImageOES image )
+void glEGLImageTargetRenderbufferStorageOES ( GLenum target, GLeglImageOES image )
+void glAlphaFuncxOES ( GLenum func, GLclampx ref )
+void glClearColorxOES ( GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha )
+void glClearDepthxOES ( GLclampx depth )
+void glClipPlanexOES ( GLenum plane, const GLfixed *equation )
+void glColor4xOES ( GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha )
+void glDepthRangexOES ( GLclampx zNear, GLclampx zFar )
+void glFogxOES ( GLenum pname, GLfixed param )
+void glFogxvOES ( GLenum pname, const GLfixed *params )
+void glFrustumxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glGetClipPlanexOES ( GLenum pname, GLfixed *eqn )
+void glGetFixedvOES ( GLenum pname, GLfixed *params )
+void glGetLightxvOES ( GLenum light, GLenum pname, GLfixed *params )
+void glGetMaterialxvOES ( GLenum face, GLenum pname, GLfixed *params )
+void glGetTexEnvxvOES ( GLenum env, GLenum pname, GLfixed *params )
+void glGetTexParameterxvOES ( GLenum target, GLenum pname, GLfixed *params )
+void glLightModelxOES ( GLenum pname, GLfixed param )
+void glLightModelxvOES ( GLenum pname, const GLfixed *params )
+void glLightxOES ( GLenum light, GLenum pname, GLfixed param )
+void glLightxvOES ( GLenum light, GLenum pname, const GLfixed *params )
+void glLineWidthxOES ( GLfixed width )
+void glLoadMatrixxOES ( const GLfixed *m )
+void glMaterialxOES ( GLenum face, GLenum pname, GLfixed param )
+void glMaterialxvOES ( GLenum face, GLenum pname, const GLfixed *params )
+void glMultMatrixxOES ( const GLfixed *m )
+void glMultiTexCoord4xOES ( GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q )
+void glNormal3xOES ( GLfixed nx, GLfixed ny, GLfixed nz )
+void glOrthoxOES ( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar )
+void glPointParameterxOES ( GLenum pname, GLfixed param )
+void glPointParameterxvOES ( GLenum pname, const GLfixed *params )
+void glPointSizexOES ( GLfixed size )
+void glPolygonOffsetxOES ( GLfixed factor, GLfixed units )
+void glRotatexOES ( GLfixed angle, GLfixed x, GLfixed y, GLfixed z )
+void glSampleCoveragexOES ( GLclampx value, GLboolean invert )
+void glScalexOES ( GLfixed x, GLfixed y, GLfixed z )
+void glTexEnvxOES ( GLenum target, GLenum pname, GLfixed param )
+void glTexEnvxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+void glTexParameterxOES ( GLenum target, GLenum pname, GLfixed param )
+void glTexParameterxvOES ( GLenum target, GLenum pname, const GLfixed *params )
+void glTranslatexOES ( GLfixed x, GLfixed y, GLfixed z )
+GLboolean glIsRenderbufferOES ( GLuint renderbuffer )
+void glBindRenderbufferOES ( GLenum target, GLuint renderbuffer )
+void glDeleteRenderbuffersOES ( GLsizei n, const GLuint *renderbuffers )
+void glGenRenderbuffersOES ( GLsizei n, GLuint *renderbuffers )
+void glRenderbufferStorageOES ( GLenum target, GLenum internalformat, GLsizei width, GLsizei height )
+void glGetRenderbufferParameterivOES ( GLenum target, GLenum pname, GLint *params )
+GLboolean glIsFramebufferOES ( GLuint framebuffer )
+void glBindFramebufferOES ( GLenum target, GLuint framebuffer )
+void glDeleteFramebuffersOES ( GLsizei n, const GLuint *framebuffers )
+void glGenFramebuffersOES ( GLsizei n, GLuint *framebuffers )
+GLenum glCheckFramebufferStatusOES ( GLenum target )
+void glFramebufferRenderbufferOES ( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer )
+void glFramebufferTexture2DOES ( GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level )
+void glGetFramebufferAttachmentParameterivOES ( GLenum target, GLenum attachment, GLenum pname, GLint *params )
+void glGenerateMipmapOES ( GLenum target )
+// Hard to export to Java:
+// void *glMapBufferOES ( GLenum target, GLenum access )
+// GLboolean glUnmapBufferOES ( GLenum target )
+// void glGetBufferPointervOES ( GLenum target, GLenum pname, void **params )
+void glCurrentPaletteMatrixOES ( GLuint matrixpaletteindex )
+void glLoadPaletteFromModelViewMatrixOES ( void )
+void glMatrixIndexPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glWeightPointerOES ( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+void glDepthRangefOES ( GLclampf zNear, GLclampf zFar )
+void glFrustumfOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glOrthofOES ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar )
+void glClipPlanefOES ( GLenum plane, const GLfloat *equation )
+void glGetClipPlanefOES ( GLenum pname, GLfloat *eqn )
+void glClearDepthfOES ( GLclampf depth )
+void glTexGenfOES ( GLenum coord, GLenum pname, GLfloat param )
+void glTexGenfvOES ( GLenum coord, GLenum pname, const GLfloat *params )
+void glTexGeniOES ( GLenum coord, GLenum pname, GLint param )
+void glTexGenivOES ( GLenum coord, GLenum pname, const GLint *params )
+void glTexGenxOES ( GLenum coord, GLenum pname, GLfixed param )
+void glTexGenxvOES ( GLenum coord, GLenum pname, const GLfixed *params )
+void glGetTexGenfvOES ( GLenum coord, GLenum pname, GLfloat *params )
+void glGetTexGenivOES ( GLenum coord, GLenum pname, GLint *params )
+void glGetTexGenxvOES ( GLenum coord, GLenum pname, GLfixed *params )
diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec
new file mode 100644
index 0000000..97dac2e
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/checks.spec
@@ -0,0 +1,61 @@
+glClipPlanef check eqn 4

+glClipPlanex check eqn 4

+glGetClipPlanefOES check eqn 4

+glGetClipPlanexOES check eqn 4

+glDeleteBuffers check buffers n 

+glDeleteTextures check textures n

+glDrawElements check_AIOOBE indices count

+glFog ifcheck params 1 pname GL_FOG_MODE,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END ifcheck params 4 pname GL_FOG_COLOR

+glGenBuffers check buffers n

+glGenTextures check textures n

+glGetClipPlane check eqn 4

+glGetIntegerv ifcheck params 1 pname GL_ALPHA_BITS,GL_ALPHA_TEST_FUNC,GL_ALPHA_TEST_REF,GL_BLEND_DST,GL_BLUE_BITS,GL_COLOR_ARRAY_BUFFER_BINDING,GL_COLOR_ARRAY_SIZE,GL_COLOR_ARRAY_STRIDE,GL_COLOR_ARRAY_TYPE,GL_CULL_FACE,GL_DEPTH_BITS,GL_DEPTH_CLEAR_VALUE,GL_DEPTH_FUNC,GL_DEPTH_WRITEMASK,GL_FOG_DENSITY,GL_FOG_END,GL_FOG_MODE,GL_FOG_START,GL_FRONT_FACE,GL_GREEN_BITS,GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES,GL_IMPLEMENTATION_COLOR_READ_TYPE_OES,GL_LIGHT_MODEL_TWO_SIDE,GL_LINE_SMOOTH_HINT,GL_LINE_WIDTH,GL_LOGIC_OP_MODE,GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES,GL_MATRIX_INDEX_ARRAY_SIZE_OES,GL_MATRIX_INDEX_ARRAY_STRIDE_OES,GL_MATRIX_INDEX_ARRAY_TYPE_OES,GL_MATRIX_MODE,GL_MAX_CLIP_PLANES,GL_MAX_ELEMENTS_INDICES,GL_MAX_ELEMENTS_VERTICES,GL_MAX_LIGHTS,GL_MAX_MODELVIEW_STACK_DEPTH,GL_MAX_PALETTE_MATRICES_OES,GL_MAX_PROJECTION_STACK_DEPTH,GL_MAX_TEXTURE_SIZE,GL_MAX_TEXTURE_STACK_DEPTH,GL_MAX_TEXTURE_UNITS,GL_MAX_VERTEX_UNITS_OES,GL_MODELVIEW_STACK_DEPTH,GL_NORMAL_ARRAY_BUFFER_BINDING,GL_NORMAL_ARRAY_STRIDE,GL_NORMAL_ARRAY_TYPE,GL_NUM_COMPRESSED_TEXTURE_FORMATS,GL_PACK_ALIGNMENT,GL_PERSPECTIVE_CORRECTION_HINT,GL_POINT_SIZE,GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES,GL_POINT_SIZE_ARRAY_STRIDE_OES,GL_POINT_SIZE_ARRAY_TYPE_OES,GL_POINT_SMOOTH_HINT,GL_POLYGON_OFFSET_FACTOR,GL_POLYGON_OFFSET_UNITS,GL_PROJECTION_STACK_DEPTH,GL_RED_BITS,GL_SHADE_MODEL,GL_STENCIL_BITS,GL_STENCIL_CLEAR_VALUE,GL_STENCIL_FAIL,GL_STENCIL_FUNC,GL_STENCIL_PASS_DEPTH_FAIL,GL_STENCIL_PASS_DEPTH_PASS,GL_STENCIL_REF,GL_STENCIL_VALUE_MASK,GL_STENCIL_WRITEMASK,GL_SUBPIXEL_BITS,GL_TEXTURE_BINDING_2D,GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING,GL_TEXTURE_COORD_ARRAY_SIZE,GL_TEXTURE_COORD_ARRAY_STRIDE,GL_TEXTURE_COORD_ARRAY_TYPE,GL_TEXTURE_STACK_DEPTH,GL_UNPACK_ALIGNMENT,GL_VERTEX_ARRAY_BUFFER_BINDING,GL_VERTEX_ARRAY_SIZE,GL_VERTEX_ARRAY_STRIDE,GL_VERTEX_ARRAY_TYPE,GL_WEIGHT_ARRAY_BUFFER_BINDING_OES,GL_WEIGHT_ARRAY_SIZE_OES,GL_WEIGHT_ARRAY_STRIDE_OES,GL_WEIGHT_ARRAY_TYPE_OES ifcheck params 2 pname GL_ALIASED_POINT_SIZE_RANGE,GL_ALIASED_LINE_WIDTH_RANGE,GL_DEPTH_RANGE,GL_MAX_VIEWPORT_DIMS,GL_SMOOTH_LINE_WIDTH_RANGE,GL_SMOOTH_POINT_SIZE_RANGE ifcheck params 4 pname GL_COLOR_CLEAR_VALUE,GL_COLOR_WRITEMASK,GL_SCISSOR_BOX,GL_VIEWPORT ifcheck params 16 pname GL_MODELVIEW_MATRIX,GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,GL_PROJECTION_MATRIX,GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES,GL_TEXTURE_MATRIX,GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES ifcheck params _NUM_COMPRESSED_TEXTURE_FORMATS pname GL_COMPRESSED_TEXTURE_FORMATS,GL_FOG_COLOR,GL_LIGHT_MODEL_AMBIENT

+glGetLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

+glGetMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

+glGetTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

+glGetTexParameter check params 1

+glLightModel ifcheck params 1 pname GL_LIGHT_MODEL_TWO_SIDE ifcheck params 4 pname GL_LIGHT_MODEL_AMBIENT

+glLight ifcheck params 1 pname GL_SPOT_EXPONENT,GL_SPOT_CUTOFF,GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION

+glLoadMatrix check m 16

+glMaterial ifcheck params 1 pname GL_SHININESS ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE

+glMultMatrix check m 16

+glPointParameter check params 1

+glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR

+glTexImage2D nullAllowed

+glTexSubImage2D nullAllowed

+glBufferData nullAllowed

+glTexParameter check params 1

+glQueryMatrixxOES check mantissa 16 check exponent 16 return -1

+glDrawTexfvOES check coords 5

+glDrawTexivOES check coords 5

+glDrawTexsvOES check coords 5

+glDrawTexxvOES check coords 5

+glBindFramebufferOES unsupported

+glBindRenderbufferOES unsupported

+glBlendEquation unsupported

+glBlendEquationSeparate unsupported

+glBlendFuncSeparate unsupported

+glCheckFramebufferStatusOES unsupported return 0

+glCurrentPaletteMatrixOES unsupported

+glDeleteFramebuffersOES unsupported

+glDeleteRenderbuffersOES unsupported

+glFramebufferRenderbufferOES unsupported

+glFramebufferStorageOES unsupported

+glFramebufferTexture2DOES unsupported

+glGenFramebuffersOES unsupported

+glGenRenderbuffersOES unsupported

+glGenerateMipmapOES unsupported

+glGetBufferParameter unsupported

+glGetFramebufferAttachmentParameterivOES unsupported

+glGetRenderbufferParameterivOES unsupported

+glGetTexGen unsupported

+glIsFramebufferOES unsupported return JNI_FALSE

+glIsRenderbufferOES unsupported return JNI_FALSE

+glLoadPaletteFromModelViewMatrixOES unsupported

+glMatrixIndexPointerOES unsupported

+glRenderbufferStorageOES unsupported return false

+glTexGen unsupported

+glTexGenf unsupported

+glTexGeni unsupported

+glTexGenx unsupported

+glWeightPointerOES unsupported

diff --git a/opengl/tools/glgen/glspec-1.0 b/opengl/tools/glgen/specs/jsr239/glspec-1.0
similarity index 100%
rename from opengl/tools/glgen/glspec-1.0
rename to opengl/tools/glgen/specs/jsr239/glspec-1.0
diff --git a/opengl/tools/glgen/glspec-1.0ext b/opengl/tools/glgen/specs/jsr239/glspec-1.0ext
similarity index 100%
rename from opengl/tools/glgen/glspec-1.0ext
rename to opengl/tools/glgen/specs/jsr239/glspec-1.0ext
diff --git a/opengl/tools/glgen/glspec-1.1 b/opengl/tools/glgen/specs/jsr239/glspec-1.1
similarity index 100%
rename from opengl/tools/glgen/glspec-1.1
rename to opengl/tools/glgen/specs/jsr239/glspec-1.1
diff --git a/opengl/tools/glgen/glspec-1.1ext b/opengl/tools/glgen/specs/jsr239/glspec-1.1ext
similarity index 100%
rename from opengl/tools/glgen/glspec-1.1ext
rename to opengl/tools/glgen/specs/jsr239/glspec-1.1ext
diff --git a/opengl/tools/glgen/glspec-1.1extpack b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
similarity index 100%
rename from opengl/tools/glgen/glspec-1.1extpack
rename to opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
diff --git a/opengl/tools/glgen/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
similarity index 100%
rename from opengl/tools/glgen/glspec-checks
rename to opengl/tools/glgen/specs/jsr239/glspec-checks
diff --git a/opengl/tools/glgen/src/.gitignore b/opengl/tools/glgen/src/.gitignore
new file mode 100644
index 0000000..6b468b6
--- /dev/null
+++ b/opengl/tools/glgen/src/.gitignore
@@ -0,0 +1 @@
+*.class
diff --git a/opengl/tools/glgen/src/CFunc.java b/opengl/tools/glgen/src/CFunc.java
index 0794f41..a89e1c5 100644
--- a/opengl/tools/glgen/src/CFunc.java
+++ b/opengl/tools/glgen/src/CFunc.java
@@ -1,155 +1,156 @@
-

-import java.util.*;

-

-public class CFunc {

-

-    String original;

-

-    CType ftype;

-    String fname;

-

-    List<String> argNames = new ArrayList<String>();

-    List<CType> argTypes = new ArrayList<CType>();

-

-    boolean hasPointerArg = false;

-    boolean hasTypedPointerArg = false;

-

-    public CFunc(String original) {

-        this.original = original;

-    }

-

-    public String getOriginal() {

-        return original;

-    }

-

-    public void setName(String fname) {

-        this.fname = fname;

-    }

-

-    public String getName() {

-        return fname;

-    }

-

-    public void setType(CType ftype) {

-        this.ftype = ftype;

-    }

-

-    public CType getType() {

-        return ftype;

-    }

-

-    public void addArgument(String argName, CType argType) {

-        argNames.add(argName);

-        argTypes.add(argType);

-

-        if (argType.isPointer()) {

-            hasPointerArg = true;

-        }

-        if (argType.isTypedPointer()) {

-            hasTypedPointerArg = true;

-        }

-    }

-

-    public int getNumArgs() {

-        return argNames.size();

-    }

-

-    public int getArgIndex(String name) {

-        int len = argNames.size();

-        for (int i = 0; i < len; i++) {

-            if (name.equals(argNames.get(i))) {

-                return i;

-            }

-        }

-        return -1;

-    }

-

-    public String getArgName(int index) {

-        return argNames.get(index);

-    }

-

-    public CType getArgType(int index) {

-        return argTypes.get(index);

-    }

-

-    public boolean hasPointerArg() {

-        return hasPointerArg;

-    }

-

-    public boolean hasTypedPointerArg() {

-        return hasTypedPointerArg;

-    }

-

-    public String toString() {

-        String s =  "Function " + fname + " returns " + ftype + ": ";

-        for (int i = 0; i < argNames.size(); i++) {

-            if (i > 0) {

-                s += ", ";

-            }

-            s += argTypes.get(i) + " " + argNames.get(i);

-        }

-        return s;

-    }

-

-    public static CFunc parseCFunc(String s) {

-        CFunc cfunc = new CFunc(s);

-        String[] tokens = s.split("\\s");

-

-        int i = 0;

-        CType ftype = new CType();

-        String ftypeName = tokens[i++];

-        if (ftypeName.equals("const")) {

-            ftype.setIsConst(true);

-            ftypeName = tokens[i++];

-        }

-        ftype.setBaseType(ftypeName);

-

-        String fname = tokens[i++];

-        if (fname.equals("*")) {

-            ftype.setIsPointer(true);

-            fname = tokens[i++];

-        }

-	

-        cfunc.setName(fname);

-        cfunc.setType(ftype);

-	

-        while (i < tokens.length) {

-            String tok = tokens[i++];

-	    

-            if (tok.equals("(")) {

-                continue;

-            }

-            if (tok.equals(")")) {

-                break;

-            }

-

-            CType argType = new CType();

-	    

-            String argTypeName = tok;

-            String argName = "";

-	    

-            if (argTypeName.equals("const")) {

-                argType.setIsConst(true);

-                argTypeName = tokens[i++];

-            }

-            argType.setBaseType(argTypeName);

-

-            if (argTypeName.equals("void")) {

-                break;

-            }

-	    

-            argName = tokens[i++];

-            if (argName.startsWith("*")) {

-                argType.setIsPointer(true);

-                argName = argName.substring(1, argName.length());

-            }

-            if (argName.endsWith(",")) {

-                argName = argName.substring(0, argName.length() - 1);

-            }

-	    

-            cfunc.addArgument(argName, argType);

-        }

-

-        return cfunc;

-    }

-}

+
+import java.util.*;
+
+public class CFunc {
+
+    String original;
+
+    CType ftype;
+    String fname;
+
+    List<String> argNames = new ArrayList<String>();
+    List<CType> argTypes = new ArrayList<CType>();
+
+    boolean hasPointerArg = false;
+    boolean hasTypedPointerArg = false;
+
+    public CFunc(String original) {
+        this.original = original;
+    }
+
+    public String getOriginal() {
+        return original;
+    }
+
+    public void setName(String fname) {
+        this.fname = fname;
+    }
+
+    public String getName() {
+        return fname;
+    }
+
+    public void setType(CType ftype) {
+        this.ftype = ftype;
+    }
+
+    public CType getType() {
+        return ftype;
+    }
+
+    public void addArgument(String argName, CType argType) {
+        argNames.add(argName);
+        argTypes.add(argType);
+
+        if (argType.isPointer()) {
+            hasPointerArg = true;
+        }
+        if (argType.isTypedPointer()) {
+            hasTypedPointerArg = true;
+        }
+    }
+
+    public int getNumArgs() {
+        return argNames.size();
+    }
+
+    public int getArgIndex(String name) {
+        int len = argNames.size();
+        for (int i = 0; i < len; i++) {
+            if (name.equals(argNames.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public String getArgName(int index) {
+        return argNames.get(index);
+    }
+
+    public CType getArgType(int index) {
+        return argTypes.get(index);
+    }
+
+    public boolean hasPointerArg() {
+        return hasPointerArg;
+    }
+
+    public boolean hasTypedPointerArg() {
+        return hasTypedPointerArg;
+    }
+
+    @Override
+    public String toString() {
+        String s =  "Function " + fname + " returns " + ftype + ": ";
+        for (int i = 0; i < argNames.size(); i++) {
+            if (i > 0) {
+                s += ", ";
+            }
+            s += argTypes.get(i) + " " + argNames.get(i);
+        }
+        return s;
+    }
+
+    public static CFunc parseCFunc(String s) {
+        CFunc cfunc = new CFunc(s);
+        String[] tokens = s.split("\\s");
+
+        int i = 0;
+        CType ftype = new CType();
+        String ftypeName = tokens[i++];
+        if (ftypeName.equals("const")) {
+            ftype.setIsConst(true);
+            ftypeName = tokens[i++];
+        }
+        ftype.setBaseType(ftypeName);
+
+        String fname = tokens[i++];
+        if (fname.equals("*")) {
+            ftype.setIsPointer(true);
+            fname = tokens[i++];
+        }
+
+        cfunc.setName(fname);
+        cfunc.setType(ftype);
+
+        while (i < tokens.length) {
+            String tok = tokens[i++];
+
+            if (tok.equals("(")) {
+                continue;
+            }
+            if (tok.equals(")")) {
+                break;
+            }
+
+            CType argType = new CType();
+
+            String argTypeName = tok;
+            String argName = "";
+
+            if (argTypeName.equals("const")) {
+                argType.setIsConst(true);
+                argTypeName = tokens[i++];
+            }
+            argType.setBaseType(argTypeName);
+
+            if (argTypeName.equals("void")) {
+                break;
+            }
+
+            argName = tokens[i++];
+            if (argName.startsWith("*")) {
+                argType.setIsPointer(true);
+                argName = argName.substring(1, argName.length());
+            }
+            if (argName.endsWith(",")) {
+                argName = argName.substring(0, argName.length() - 1);
+            }
+
+            cfunc.addArgument(argName, argType);
+        }
+
+        return cfunc;
+    }
+}
diff --git a/opengl/tools/glgen/src/CType.java b/opengl/tools/glgen/src/CType.java
index 331ec62..826c90d 100644
--- a/opengl/tools/glgen/src/CType.java
+++ b/opengl/tools/glgen/src/CType.java
@@ -1,85 +1,88 @@
-

-public class CType {

-

-    String baseType;

-    boolean isConst;

-    boolean isPointer;

-

-    public CType() {

-    }

-

-    public CType(String baseType) {

-	setBaseType(baseType);

-    }

-

-    public CType(String baseType, boolean isConst, boolean isPointer) {

-	setBaseType(baseType);

-	setIsConst(isConst);

-	setIsPointer(isPointer);

-    }

-

-    public String getDeclaration() {

-	return baseType + (isPointer ? " *" : "");

-    }

-    

-    public void setIsConst(boolean isConst) {

-	this.isConst = isConst;

-    }

-

-    public boolean isConst() {

-	return isConst;

-    }

-

-    public void setIsPointer(boolean isPointer) {

-	this.isPointer = isPointer;

-    }

-

-    public boolean isPointer() {

-	return isPointer;

-    }

-

-    boolean isVoid() {

-	String baseType = getBaseType();

-	return baseType.equals("GLvoid") ||

-	    baseType.equals("void");

-    }

-

-    public boolean isTypedPointer() {

-	return isPointer() && !isVoid();

-    }

-

-    public void setBaseType(String baseType) {

-	this.baseType = baseType;

-    }

-

-    public String getBaseType() {

-	return baseType;

-    }

-

-    public String toString() {

-	String s = "";

-	if (isConst()) {

-	    s += "const ";

-	}

-	s += baseType;

-	if (isPointer()) {

-	    s += "*";

-	}

-

-	return s;

-    }

-

-    public int hashCode() {

-	return baseType.hashCode() ^ (isPointer ? 2 : 0) ^ (isConst ? 1 : 0);

-    }

-

-    public boolean equals(Object o) {

-	if (o != null && o instanceof CType) {

-	    CType c = (CType)o;

-	    return baseType.equals(c.baseType) &&

-		isPointer() == c.isPointer() &&

-		isConst() == c.isConst();

-	}

-	return false;

-    }

-}

+
+public class CType {
+
+    String baseType;
+    boolean isConst;
+    boolean isPointer;
+
+    public CType() {
+    }
+
+    public CType(String baseType) {
+    setBaseType(baseType);
+    }
+
+    public CType(String baseType, boolean isConst, boolean isPointer) {
+    setBaseType(baseType);
+    setIsConst(isConst);
+    setIsPointer(isPointer);
+    }
+
+    public String getDeclaration() {
+    return baseType + (isPointer ? " *" : "");
+    }
+
+    public void setIsConst(boolean isConst) {
+    this.isConst = isConst;
+    }
+
+    public boolean isConst() {
+    return isConst;
+    }
+
+    public void setIsPointer(boolean isPointer) {
+    this.isPointer = isPointer;
+    }
+
+    public boolean isPointer() {
+    return isPointer;
+    }
+
+    boolean isVoid() {
+    String baseType = getBaseType();
+    return baseType.equals("GLvoid") ||
+        baseType.equals("void");
+    }
+
+    public boolean isTypedPointer() {
+    return isPointer() && !isVoid();
+    }
+
+    public void setBaseType(String baseType) {
+    this.baseType = baseType;
+    }
+
+    public String getBaseType() {
+    return baseType;
+    }
+
+    @Override
+    public String toString() {
+    String s = "";
+    if (isConst()) {
+        s += "const ";
+    }
+    s += baseType;
+    if (isPointer()) {
+        s += "*";
+    }
+
+    return s;
+    }
+
+    @Override
+    public int hashCode() {
+    return baseType.hashCode() ^ (isPointer ? 2 : 0) ^ (isConst ? 1 : 0);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+    if (o != null && o instanceof CType) {
+        CType c = (CType)o;
+        return baseType.equals(c.baseType) &&
+        isPointer() == c.isPointer() &&
+        isConst() == c.isConst();
+    }
+    return false;
+    }
+}
diff --git a/opengl/tools/glgen/src/CodeEmitter.java b/opengl/tools/glgen/src/CodeEmitter.java
index 3e9b90a..ebb9727 100644
--- a/opengl/tools/glgen/src/CodeEmitter.java
+++ b/opengl/tools/glgen/src/CodeEmitter.java
@@ -1,8 +1,8 @@
-

-public interface CodeEmitter {

-

-    void setVersion(int version, boolean ext, boolean pack);

-    void emitCode(CFunc cfunc, String original);

-    void addNativeRegistration(String fname);

-    void emitNativeRegistration();

-}

+
+public interface CodeEmitter {
+
+    void setVersion(int version, boolean ext, boolean pack);
+    void emitCode(CFunc cfunc, String original);
+    void addNativeRegistration(String fname);
+    void emitNativeRegistration();
+}
diff --git a/opengl/tools/glgen/src/GLESCodeEmitter.java b/opengl/tools/glgen/src/GLESCodeEmitter.java
new file mode 100644
index 0000000..b303503
--- /dev/null
+++ b/opengl/tools/glgen/src/GLESCodeEmitter.java
@@ -0,0 +1,40 @@
+import java.io.PrintStream;
+
+/**
+ * Emits a Java interface and Java & C implementation for a C function.
+ *
+ * <p> The Java interface will have Buffer and array variants for functions that
+ * have a typed pointer argument.  The array variant will convert a single "<type> *data"
+ * argument to a pair of arguments "<type>[] data, int offset".
+ */
+public class GLESCodeEmitter extends JniCodeEmitter {
+
+    PrintStream mJavaImplStream;
+    PrintStream mCStream;
+
+    PrintStream mJavaInterfaceStream;
+
+    /**
+      */
+    public GLESCodeEmitter(String classPathName,
+                          ParameterChecker checker,
+                          PrintStream javaImplStream,
+                          PrintStream cStream) {
+        mClassPathName = classPathName;
+        mChecker = checker;
+
+        mJavaImplStream = javaImplStream;
+        mCStream = cStream;
+        mUseContextPointer = false;
+        mUseStaticMethods = true;
+    }
+
+    public void emitCode(CFunc cfunc, String original) {
+        emitCode(cfunc, original, null, mJavaImplStream,
+                mCStream);
+    }
+
+    public void emitNativeRegistration(String nativeRegistrationName) {
+        emitNativeRegistration(nativeRegistrationName, mCStream);
+    }
+}
diff --git a/opengl/tools/glgen/src/GenerateGL.java b/opengl/tools/glgen/src/GenerateGL.java
index 657ee6e..3715a96 100644
--- a/opengl/tools/glgen/src/GenerateGL.java
+++ b/opengl/tools/glgen/src/GenerateGL.java
@@ -1,164 +1,167 @@
-

-import java.io.*;

-import java.util.*;

-

-public class GenerateGL {

-

-    static void copy(String filename, PrintStream out) throws IOException {

-        BufferedReader br = new BufferedReader(new FileReader(filename));

-        String s;

-        while ((s = br.readLine()) != null) {

-            out.println(s);

-        }

-    }

-

-    private static void emit(int version, boolean ext, boolean pack,

-                             CodeEmitter emitter,

-                             BufferedReader specReader,

-                             PrintStream glStream,

-                             PrintStream glImplStream,

-                             PrintStream cStream) throws Exception {

-        String s = null;

-        int counter = 0;

-        while ((s = specReader.readLine()) != null) {

-            if (s.trim().startsWith("//")) {

-                continue;

-            }

-

-            CFunc cfunc = CFunc.parseCFunc(s);

-

-            String fname = cfunc.getName();

-            File f = new File("stubs/" + fname +

-                              ".java-1" + version + "-if");

-            if (f.exists()) {

-                System.out.println("Special-casing function " + fname);

-                copy("stubs/" + fname +

-                     ".java-1" + version + "-if", glStream);

-                copy("stubs/" + fname + ".java-impl", glImplStream);

-                copy("stubs/" + fname + ".cpp", cStream);

-

-                // Register native function names

-                // This should be improved to require fewer discrete files

-                String filename = "stubs/" + fname + ".nativeReg";

-                BufferedReader br =

-                    new BufferedReader(new FileReader(filename));

-                String nfunc;

-                while ((nfunc = br.readLine()) != null) {

-                    emitter.addNativeRegistration(nfunc);

-                }

-            } else {

-                emitter.setVersion(version, ext, pack);

-                emitter.emitCode(cfunc, s);

-            }

-        }

-    }

-

-    public static void main(String[] args) throws Exception {

-        String classPathName = "com/google/android/gles_jni/GLImpl";

-        boolean useContextPointer = true;

-

-        int aidx = 0;

-        while (args[aidx].charAt(0) == '-') {

-            switch (args[aidx].charAt(1)) {

-            case 'c':

-                useContextPointer = false;

-                break;

-

-            default:

-                System.err.println("Unknown flag: " + args[aidx]);

-                System.exit(1);

-            }

-

-            aidx++;

-        }

-

-        System.out.println("useContextPointer = " + useContextPointer);

-

-        BufferedReader spec10Reader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec10ExtReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11Reader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11ExtReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11ExtPackReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader checksReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-

-        String gl10Filename = "javax/microedition/khronos/opengles/GL10.java";

-        String gl10ExtFilename =

-            "javax/microedition/khronos/opengles/GL10Ext.java";

-        String gl11Filename = "javax/microedition/khronos/opengles/GL11.java";

-        String gl11ExtFilename =

-            "javax/microedition/khronos/opengles/GL11Ext.java";

-        String gl11ExtPackFilename =

-            "javax/microedition/khronos/opengles/GL11ExtensionPack.java";

-        String glImplFilename = "com/google/android/gles_jni/GLImpl.java";

-        String cFilename = "com_google_android_gles_jni_GLImpl.cpp";

-

-        PrintStream gl10Stream =

-            new PrintStream(new FileOutputStream("out/" + gl10Filename));

-        PrintStream gl10ExtStream =

-            new PrintStream(new FileOutputStream("out/" + gl10ExtFilename));

-        PrintStream gl11Stream =

-            new PrintStream(new FileOutputStream("out/" + gl11Filename));

-        PrintStream gl11ExtStream =

-            new PrintStream(new FileOutputStream("out/" + gl11ExtFilename));

-        PrintStream gl11ExtPackStream =

-            new PrintStream(new FileOutputStream("out/" + gl11ExtPackFilename));

-        PrintStream glImplStream =

-            new PrintStream(new FileOutputStream("out/" + glImplFilename));

-        PrintStream cStream =

-            new PrintStream(new FileOutputStream("out/" + cFilename));

-

-        ParameterChecker checker = new ParameterChecker(checksReader);

-

-        CodeEmitter emitter =

-            new JniCodeEmitter(classPathName,

-                               checker,

-                               gl10Stream, gl10ExtStream,

-                               gl11Stream, gl11ExtStream, gl11ExtPackStream,

-                               glImplStream, cStream,

-                               useContextPointer);

-

-        gl10Stream.println("/* //device/java/android/" + gl10Filename);

-        gl10ExtStream.println("/* //device/java/android/" + gl10ExtFilename);

-        gl11Stream.println("/* //device/java/android/" + gl11Filename);

-        gl11ExtStream.println("/* //device/java/android/" + gl11ExtFilename);

-        gl11ExtPackStream.println("/* //device/java/android/" +

-            gl11ExtPackFilename);

-        glImplStream.println("/* //device/java/android/" + glImplFilename);

-        cStream.println("/* //device/libs/android_runtime/" + cFilename);

-

-        copy("stubs/GL10Header.java-if", gl10Stream);

-        copy("stubs/GL10ExtHeader.java-if", gl10ExtStream);

-        copy("stubs/GL11Header.java-if", gl11Stream);

-        copy("stubs/GL11ExtHeader.java-if", gl11ExtStream);

-        copy("stubs/GL11ExtensionPackHeader.java-if", gl11ExtPackStream);

-        copy("stubs/GLImplHeader.java-impl", glImplStream);

-        copy("stubs/GLCHeader.cpp", cStream);

-

-        emit(0, false, false,

-             emitter, spec10Reader, gl10Stream, glImplStream, cStream);

-        emit(0, true, false,

-             emitter, spec10ExtReader, gl10ExtStream, glImplStream, cStream);

-        emit(1, false, false,

-             emitter, spec11Reader, gl11Stream, glImplStream, cStream);

-        emit(1, true, false,

-             emitter, spec11ExtReader, gl11ExtStream, glImplStream, cStream);

-        emit(1, true, true,

-             emitter, spec11ExtPackReader, gl11ExtPackStream, glImplStream,

-             cStream);

-

-        emitter.emitNativeRegistration();

-

-        gl10Stream.println("}");

-        gl10ExtStream.println("}");

-        gl11Stream.println("}");

-        gl11ExtStream.println("}");

-        gl11ExtPackStream.println("}");

-        glImplStream.println("}");

-    }

-}

+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class GenerateGL {
+
+    static void copy(String filename, PrintStream out) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader(filename));
+        String s;
+        while ((s = br.readLine()) != null) {
+            out.println(s);
+        }
+    }
+
+    private static void emit(int version, boolean ext, boolean pack,
+                             CodeEmitter emitter,
+                             BufferedReader specReader,
+                             PrintStream glStream,
+                             PrintStream glImplStream,
+                             PrintStream cStream) throws Exception {
+        String s = null;
+        while ((s = specReader.readLine()) != null) {
+            if (s.trim().startsWith("//")) {
+                continue;
+            }
+
+            CFunc cfunc = CFunc.parseCFunc(s);
+
+            String fname = cfunc.getName();
+            File f = new File("stubs/jsr239/" + fname +
+                              ".java-1" + version + "-if");
+            if (f.exists()) {
+                System.out.println("Special-casing function " + fname);
+                copy("stubs/jsr239/" + fname +
+                     ".java-1" + version + "-if", glStream);
+                copy("stubs/jsr239/" + fname + ".java-impl", glImplStream);
+                copy("stubs/jsr239/" + fname + ".cpp", cStream);
+
+                // Register native function names
+                // This should be improved to require fewer discrete files
+                String filename = "stubs/jsr239/" + fname + ".nativeReg";
+                BufferedReader br =
+                    new BufferedReader(new FileReader(filename));
+                String nfunc;
+                while ((nfunc = br.readLine()) != null) {
+                    emitter.addNativeRegistration(nfunc);
+                }
+            } else {
+                emitter.setVersion(version, ext, pack);
+                emitter.emitCode(cfunc, s);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        String classPathName = "com/google/android/gles_jni/GLImpl";
+        boolean useContextPointer = true;
+
+        int aidx = 0;
+        while (args[aidx].charAt(0) == '-') {
+            switch (args[aidx].charAt(1)) {
+            case 'c':
+                useContextPointer = false;
+                break;
+
+            default:
+                System.err.println("Unknown flag: " + args[aidx]);
+                System.exit(1);
+            }
+
+            aidx++;
+        }
+
+        System.out.println("useContextPointer = " + useContextPointer);
+
+        BufferedReader spec10Reader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec10ExtReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11Reader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11ExtReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11ExtPackReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader checksReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+
+        String gl10Filename = "javax/microedition/khronos/opengles/GL10.java";
+        String gl10ExtFilename =
+            "javax/microedition/khronos/opengles/GL10Ext.java";
+        String gl11Filename = "javax/microedition/khronos/opengles/GL11.java";
+        String gl11ExtFilename =
+            "javax/microedition/khronos/opengles/GL11Ext.java";
+        String gl11ExtPackFilename =
+            "javax/microedition/khronos/opengles/GL11ExtensionPack.java";
+        String glImplFilename = "com/google/android/gles_jni/GLImpl.java";
+        String cFilename = "com_google_android_gles_jni_GLImpl.cpp";
+
+        PrintStream gl10Stream =
+            new PrintStream(new FileOutputStream("out/" + gl10Filename));
+        PrintStream gl10ExtStream =
+            new PrintStream(new FileOutputStream("out/" + gl10ExtFilename));
+        PrintStream gl11Stream =
+            new PrintStream(new FileOutputStream("out/" + gl11Filename));
+        PrintStream gl11ExtStream =
+            new PrintStream(new FileOutputStream("out/" + gl11ExtFilename));
+        PrintStream gl11ExtPackStream =
+            new PrintStream(new FileOutputStream("out/" + gl11ExtPackFilename));
+        PrintStream glImplStream =
+            new PrintStream(new FileOutputStream("out/" + glImplFilename));
+        PrintStream cStream =
+            new PrintStream(new FileOutputStream("out/" + cFilename));
+
+        ParameterChecker checker = new ParameterChecker(checksReader);
+
+        CodeEmitter emitter =
+            new Jsr239CodeEmitter(classPathName,
+                               checker,
+                               gl10Stream, gl10ExtStream,
+                               gl11Stream, gl11ExtStream, gl11ExtPackStream,
+                               glImplStream, cStream,
+                               useContextPointer);
+
+        gl10Stream.println("/* //device/java/android/" + gl10Filename);
+        gl10ExtStream.println("/* //device/java/android/" + gl10ExtFilename);
+        gl11Stream.println("/* //device/java/android/" + gl11Filename);
+        gl11ExtStream.println("/* //device/java/android/" + gl11ExtFilename);
+        gl11ExtPackStream.println("/* //device/java/android/" +
+            gl11ExtPackFilename);
+        glImplStream.println("/* //device/java/android/" + glImplFilename);
+        cStream.println("/* //device/libs/android_runtime/" + cFilename);
+
+        copy("stubs/jsr239/GL10Header.java-if", gl10Stream);
+        copy("stubs/jsr239/GL10ExtHeader.java-if", gl10ExtStream);
+        copy("stubs/jsr239/GL11Header.java-if", gl11Stream);
+        copy("stubs/jsr239/GL11ExtHeader.java-if", gl11ExtStream);
+        copy("stubs/jsr239/GL11ExtensionPackHeader.java-if", gl11ExtPackStream);
+        copy("stubs/jsr239/GLImplHeader.java-impl", glImplStream);
+        copy("stubs/jsr239/GLCHeader.cpp", cStream);
+
+        emit(0, false, false,
+             emitter, spec10Reader, gl10Stream, glImplStream, cStream);
+        emit(0, true, false,
+             emitter, spec10ExtReader, gl10ExtStream, glImplStream, cStream);
+        emit(1, false, false,
+             emitter, spec11Reader, gl11Stream, glImplStream, cStream);
+        emit(1, true, false,
+             emitter, spec11ExtReader, gl11ExtStream, glImplStream, cStream);
+        emit(1, true, true,
+             emitter, spec11ExtPackReader, gl11ExtPackStream, glImplStream,
+             cStream);
+
+        emitter.emitNativeRegistration();
+
+        gl10Stream.println("}");
+        gl10ExtStream.println("}");
+        gl11Stream.println("}");
+        gl11ExtStream.println("}");
+        gl11ExtPackStream.println("}");
+        glImplStream.println("}");
+    }
+}
diff --git a/opengl/tools/glgen/src/GenerateGLES.java b/opengl/tools/glgen/src/GenerateGLES.java
new file mode 100644
index 0000000..60775b7
--- /dev/null
+++ b/opengl/tools/glgen/src/GenerateGLES.java
@@ -0,0 +1,99 @@
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class GenerateGLES {
+
+    static void copy(String filename, PrintStream out) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader(filename));
+        String s;
+        while ((s = br.readLine()) != null) {
+            out.println(s);
+        }
+    }
+
+    private static void emit(GLESCodeEmitter emitter,
+                             BufferedReader specReader,
+                             PrintStream glStream,
+                             PrintStream cStream) throws Exception {
+        String s = null;
+        while ((s = specReader.readLine()) != null) {
+            if (s.trim().startsWith("//")) {
+                continue;
+            }
+
+            CFunc cfunc = CFunc.parseCFunc(s);
+
+            String fname = cfunc.getName();
+            String stubRoot = "stubs/gles11/" + fname;
+            String javaPath = stubRoot + ".java";
+            File f = new File(javaPath);
+            if (f.exists()) {
+                System.out.println("Special-casing function " + fname);
+                copy(javaPath, glStream);
+                copy(stubRoot + ".cpp", cStream);
+
+                // Register native function names
+                // This should be improved to require fewer discrete files
+                String filename = stubRoot + ".nativeReg";
+                BufferedReader br =
+                    new BufferedReader(new FileReader(filename));
+                String nfunc;
+                while ((nfunc = br.readLine()) != null) {
+                    emitter.addNativeRegistration(nfunc);
+                }
+            } else {
+                emitter.emitCode(cfunc, s);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        int aidx = 0;
+        while ((aidx < args.length) && (args[aidx].charAt(0) == '-')) {
+            switch (args[aidx].charAt(1)) {
+            default:
+                System.err.println("Unknown flag: " + args[aidx]);
+                System.exit(1);
+            }
+
+            aidx++;
+        }
+
+        BufferedReader checksReader =
+            new BufferedReader(new FileReader("specs/gles11/checks.spec"));
+        ParameterChecker checker = new ParameterChecker(checksReader);
+
+        // Generate files
+        for(String suffix: new String[] {"GLES10", "GLES10Ext",
+                "GLES11", "GLES11Ext"})
+        {
+            BufferedReader spec11Reader =
+                new BufferedReader(new FileReader("specs/gles11/"
+                        + suffix + ".spec"));
+            String gl11Filename = "android/opengl/" + suffix + ".java";
+            String gl11cFilename = "android_opengl_" + suffix + ".cpp";
+            PrintStream gl11Stream =
+                new PrintStream(new FileOutputStream("out/" + gl11Filename));
+            PrintStream gl11cStream =
+                new PrintStream(new FileOutputStream("out/" + gl11cFilename));
+            gl11Stream.println("/*");
+            gl11cStream.println("/*");
+            copy("stubs/gles11/" + suffix + "Header.java-if", gl11Stream);
+            copy("stubs/gles11/" + suffix + "cHeader.cpp", gl11cStream);
+            GLESCodeEmitter emitter = new GLESCodeEmitter(
+                    "android/opengl/" + suffix,
+                    checker, gl11Stream, gl11cStream);
+            emit(emitter, spec11Reader, gl11Stream, gl11cStream);
+            emitter.emitNativeRegistration("register_android_opengl_jni_"
+                    + suffix);
+            gl11Stream.println("}");
+            gl11Stream.close();
+            gl11cStream.close();
+        }
+    }
+}
diff --git a/opengl/tools/glgen/src/JFunc.java b/opengl/tools/glgen/src/JFunc.java
index 42d466c..63c045b 100644
--- a/opengl/tools/glgen/src/JFunc.java
+++ b/opengl/tools/glgen/src/JFunc.java
@@ -1,148 +1,154 @@
-

-import java.util.ArrayList;

-import java.util.List;

-

-public class JFunc {

-

-    String className = "com.google.android.gles_jni.GL11Impl";

-

-    CFunc cfunc;

-    JType ftype;

-    String fname;

-

-    List<String> argNames = new ArrayList<String>();

-    List<JType> argTypes = new ArrayList<JType>();

-    List<Integer> argCIndices = new ArrayList<Integer>();

-

-    boolean hasBufferArg = false;

-    boolean hasTypedBufferArg = false;

-    ArrayList<String> bufferArgNames = new ArrayList<String>();

-

-    public JFunc(CFunc cfunc) {

-        this.cfunc = cfunc;

-    }

-

-    public CFunc getCFunc() {

-        return cfunc;

-    }

-

-    public void setName(String fname) {

-        this.fname = fname;

-    }

-

-    public String getName() {

-        return fname;

-    }

-

-    public void setType(JType ftype) {

-        this.ftype = ftype;

-    }

-

-    public JType getType() {

-        return ftype;

-    }

-

-    public void setClassName(String className) {

-        this.className = className;

-    }

-

-    public String getClassName() {

-        return className;

-    }

-    

-    public boolean hasBufferArg() {

-        return hasBufferArg;

-    }

-

-    public boolean hasTypedBufferArg() {

-        return hasTypedBufferArg;

-    }

-

-    public String getBufferArgName(int index) {

-        return bufferArgNames.get(index);

-    }

-

-    public void addArgument(String argName, JType argType, int cindex) {

-        argNames.add(argName);

-        argTypes.add(argType);

-        argCIndices.add(new Integer(cindex));

-

-        if (argType.isBuffer()) {

-            hasBufferArg = true;

-            bufferArgNames.add(argName);

-        }

-        if (argType.isTypedBuffer()) {

-            hasTypedBufferArg = true;

-            bufferArgNames.add(argName);

-        }

-    }

-

-    public int getNumArgs() {

-        return argNames.size();

-    }

-

-    public int getArgIndex(String name) {

-        int len = argNames.size();

-        for (int i = 0; i < len; i++) {

-            if (name.equals(argNames.get(i))) {

-                return i;

-            }

-        }

-        return -1;

-    }

-

-    public String getArgName(int index) {

-        return argNames.get(index);

-    }

-

-    public JType getArgType(int index) {

-        return argTypes.get(index);

-    }

-

-    public int getArgCIndex(int index) {

-        return argCIndices.get(index).intValue();

-    }

-

-    public static JFunc convert(CFunc cfunc, boolean useArray) {

-        JFunc jfunc = new JFunc(cfunc);

-        jfunc.setName(cfunc.getName());

-        jfunc.setType(JType.convert(cfunc.getType(), false));

-	

-        int numArgs = cfunc.getNumArgs();

-        int numOffsets = 0;

-        for (int i = 0; i < numArgs; i++) {

-            CType cArgType = cfunc.getArgType(i);

-            if (cArgType.isTypedPointer() && useArray) {

-                ++numOffsets;

-            }

-        }

-

-        for (int i = 0; i < numArgs; i++) {

-            String cArgName = cfunc.getArgName(i);

-            CType cArgType = cfunc.getArgType(i);

-

-            jfunc.addArgument(cArgName, JType.convert(cArgType, useArray), i);

-            if (cArgType.isTypedPointer() && useArray) {

-                if (numOffsets > 1) {

-                    jfunc.addArgument(cArgName + "Offset", new JType("int"), i);

-                } else {

-                    jfunc.addArgument("offset", new JType("int"), i);

-                }

-            }

-        }

-

-        return jfunc;

-    }

-

-    public String toString() {

-        String s =  "Function " + fname + " returns " + ftype + ": ";

-        for (int i = 0; i < argNames.size(); i++) {

-            if (i > 0) {

-                s += ", ";

-            }

-            s += argTypes.get(i) + " " + argNames.get(i);

-        }

-        return s;

-    }

-

-}

+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JFunc {
+
+    String className = "com.google.android.gles_jni.GL11Impl";
+
+    CFunc cfunc;
+    JType ftype;
+    String fname;
+
+    List<String> argNames = new ArrayList<String>();
+    List<JType> argTypes = new ArrayList<JType>();
+    List<Integer> argCIndices = new ArrayList<Integer>();
+
+    boolean hasBufferArg = false;
+    boolean hasTypedBufferArg = false;
+    ArrayList<String> bufferArgNames = new ArrayList<String>();
+
+    public JFunc(CFunc cfunc) {
+        this.cfunc = cfunc;
+    }
+
+    public CFunc getCFunc() {
+        return cfunc;
+    }
+
+    public void setName(String fname) {
+        this.fname = fname;
+    }
+
+    public String getName() {
+        return fname;
+    }
+
+    public void setType(JType ftype) {
+        this.ftype = ftype;
+    }
+
+    public JType getType() {
+        return ftype;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public boolean hasBufferArg() {
+        return hasBufferArg;
+    }
+
+    public boolean hasTypedBufferArg() {
+        return hasTypedBufferArg;
+    }
+
+    public String getBufferArgName(int index) {
+        return bufferArgNames.get(index);
+    }
+
+    public void addArgument(String argName, JType argType, int cindex) {
+        argNames.add(argName);
+        argTypes.add(argType);
+        argCIndices.add(new Integer(cindex));
+
+        if (argType.isBuffer()) {
+            hasBufferArg = true;
+            bufferArgNames.add(argName);
+        }
+        if (argType.isTypedBuffer()) {
+            hasTypedBufferArg = true;
+            bufferArgNames.add(argName);
+        }
+    }
+
+    public int getNumArgs() {
+        return argNames.size();
+    }
+
+    public int getArgIndex(String name) {
+        int len = argNames.size();
+        for (int i = 0; i < len; i++) {
+            if (name.equals(argNames.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public String getArgName(int index) {
+        return argNames.get(index);
+    }
+
+    public JType getArgType(int index) {
+        return argTypes.get(index);
+    }
+
+    public int getArgCIndex(int index) {
+        return argCIndices.get(index).intValue();
+    }
+
+    public static JFunc convert(CFunc cfunc, boolean useArray) {
+        try {
+            JFunc jfunc = new JFunc(cfunc);
+            jfunc.setName(cfunc.getName());
+            jfunc.setType(JType.convert(cfunc.getType(), false));
+
+            int numArgs = cfunc.getNumArgs();
+            int numOffsets = 0;
+            for (int i = 0; i < numArgs; i++) {
+                CType cArgType = cfunc.getArgType(i);
+                if (cArgType.isTypedPointer() && useArray) {
+                    ++numOffsets;
+                }
+            }
+
+            for (int i = 0; i < numArgs; i++) {
+                String cArgName = cfunc.getArgName(i);
+                CType cArgType = cfunc.getArgType(i);
+
+                jfunc.addArgument(cArgName, JType.convert(cArgType, useArray), i);
+                if (cArgType.isTypedPointer() && useArray) {
+                    if (numOffsets > 1) {
+                        jfunc.addArgument(cArgName + "Offset", new JType("int"), i);
+                    } else {
+                        jfunc.addArgument("offset", new JType("int"), i);
+                    }
+                }
+            }
+
+            return jfunc;
+        } catch (RuntimeException e) {
+            System.err.println("Failed to convert function " + cfunc);
+            throw e;
+        }
+    }
+
+    @Override
+    public String toString() {
+        String s =  "Function " + fname + " returns " + ftype + ": ";
+        for (int i = 0; i < argNames.size(); i++) {
+            if (i > 0) {
+                s += ", ";
+            }
+            s += argTypes.get(i) + " " + argNames.get(i);
+        }
+        return s;
+    }
+
+}
diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java
index a16d440..df1177b 100644
--- a/opengl/tools/glgen/src/JType.java
+++ b/opengl/tools/glgen/src/JType.java
@@ -1,139 +1,142 @@
-

-import java.util.HashMap;

-

-public class JType {

-    

-    String baseType;

-    boolean isArray;

-    boolean isClass;

-

-    static HashMap<CType,JType> typeMapping = new HashMap<CType,JType>();

-    static HashMap<CType,JType> arrayTypeMapping = new HashMap<CType,JType>();

-

-    static {

-	// Primitive types

-	typeMapping.put(new CType("GLbitfield"), new JType("int"));

-	typeMapping.put(new CType("GLboolean"), new JType("boolean"));

-	typeMapping.put(new CType("GLclampf"), new JType("float"));

-	typeMapping.put(new CType("GLclampx"), new JType("int"));

-	typeMapping.put(new CType("GLenum"), new JType("int"));

-	typeMapping.put(new CType("GLfloat"), new JType("float"));

-	typeMapping.put(new CType("GLfixed"), new JType("int"));

-	typeMapping.put(new CType("GLint"), new JType("int"));

-	typeMapping.put(new CType("GLintptr"), new JType("int"));

-	typeMapping.put(new CType("GLshort"), new JType("short"));

-	typeMapping.put(new CType("GLsizei"), new JType("int"));

-	typeMapping.put(new CType("GLsizeiptr"), new JType("int"));

-	typeMapping.put(new CType("GLubyte"), new JType("byte"));

-	typeMapping.put(new CType("GLuint"), new JType("int"));

-	typeMapping.put(new CType("void"), new JType("void"));

-	typeMapping.put(new CType("GLubyte", true, true), new JType("String"));

-

-	// Untyped pointers map to untyped Buffers

-	typeMapping.put(new CType("GLvoid", true, true),

-			new JType("java.nio.Buffer", true, false));

-	typeMapping.put(new CType("GLvoid", false, true),

-			new JType("java.nio.Buffer", true, false));

-	typeMapping.put(new CType("void", false, true),

-			new JType("java.nio.Buffer", true, false));

-

-	// Typed pointers map to typed Buffers

-	typeMapping.put(new CType("GLboolean", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfixed", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfixed", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfloat", false, true),

-			new JType("java.nio.FloatBuffer", true, false));

-	typeMapping.put(new CType("GLfloat", true, true),

-			new JType("java.nio.FloatBuffer", true, false));

-	typeMapping.put(new CType("GLint", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLint", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLuint", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLuint", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLshort", true, true),

-			new JType("java.nio.ShortBuffer", true, false));

-

-	// Typed pointers map to arrays + offsets

-	arrayTypeMapping.put(new CType("GLboolean", false, true),

-			     new JType("boolean", false, true));

-	arrayTypeMapping.put(new CType("GLfixed", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLfixed", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLfloat", false, true), new JType("float", false, true));

-	arrayTypeMapping.put(new CType("GLfloat", true, true), new JType("float", false, true));

-	arrayTypeMapping.put(new CType("GLint", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLint", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLshort", true, true), new JType("short", false, true));

-	arrayTypeMapping.put(new CType("GLuint", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLuint", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLintptr"), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLsizeiptr"), new JType("int", false, true));

-    }

-

-    public JType() {

-    }

-

-    public JType(String primitiveTypeName) {

-	this.baseType = primitiveTypeName;

-	this.isClass = false;

-	this.isArray = false;

-    }

-

-    public JType(String primitiveTypeName, boolean isClass, boolean isArray) {

-	this.baseType = primitiveTypeName;

-	this.isClass = isClass;

-	this.isArray = isArray;

-    }

-

-    public String getBaseType() {

-	return baseType;

-    }

-

-    public String toString() {

-	return baseType + (isArray ? "[]" : "");

-    }

-

-    public boolean isArray() {

-	return isArray;

-    }

-

-    public boolean isClass() {

-	return isClass;

-    }

-

-    public boolean isPrimitive() {

-	return !isClass() && !isArray();

-    }

-

-    public boolean isVoid() {

-	return baseType.equals("void");

-    }

-

-    public boolean isBuffer() {

-	return baseType.indexOf("Buffer") != -1;

-    }

-

-    public boolean isTypedBuffer() {

-	return !baseType.equals("java.nio.Buffer") &&

-	    (baseType.indexOf("Buffer") != -1);

-    }

-

-    public static JType convert(CType ctype, boolean useArray) {

- 	JType javaType = null;

- 	if (useArray) {

- 	    javaType = arrayTypeMapping.get(ctype);

- 	}

- 	if (javaType == null) {

- 	    javaType = typeMapping.get(ctype);

- 	}

- 	if (javaType == null) {

- 	    throw new RuntimeException("Unsupported C type: " + ctype);

- 	}

- 	return javaType;

-    }

-}

+
+import java.util.HashMap;
+
+public class JType {
+
+    String baseType;
+    boolean isArray;
+    boolean isClass;
+
+    static HashMap<CType,JType> typeMapping = new HashMap<CType,JType>();
+    static HashMap<CType,JType> arrayTypeMapping = new HashMap<CType,JType>();
+
+    static {
+    // Primitive types
+    typeMapping.put(new CType("GLbitfield"), new JType("int"));
+    typeMapping.put(new CType("GLboolean"), new JType("boolean"));
+    typeMapping.put(new CType("GLclampf"), new JType("float"));
+    typeMapping.put(new CType("GLclampx"), new JType("int"));
+    typeMapping.put(new CType("GLenum"), new JType("int"));
+    typeMapping.put(new CType("GLfloat"), new JType("float"));
+    typeMapping.put(new CType("GLfixed"), new JType("int"));
+    typeMapping.put(new CType("GLint"), new JType("int"));
+    typeMapping.put(new CType("GLintptr"), new JType("int"));
+    typeMapping.put(new CType("GLshort"), new JType("short"));
+    typeMapping.put(new CType("GLsizei"), new JType("int"));
+    typeMapping.put(new CType("GLsizeiptr"), new JType("int"));
+    typeMapping.put(new CType("GLubyte"), new JType("byte"));
+    typeMapping.put(new CType("GLuint"), new JType("int"));
+    typeMapping.put(new CType("void"), new JType("void"));
+    typeMapping.put(new CType("GLubyte", true, true), new JType("String"));
+
+    // Untyped pointers map to untyped Buffers
+    typeMapping.put(new CType("GLvoid", true, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("GLvoid", false, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("void", false, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("GLeglImageOES", false, false),
+            new JType("java.nio.Buffer", true, false));
+
+    // Typed pointers map to typed Buffers
+    typeMapping.put(new CType("GLboolean", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfixed", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfixed", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfloat", false, true),
+            new JType("java.nio.FloatBuffer", true, false));
+    typeMapping.put(new CType("GLfloat", true, true),
+            new JType("java.nio.FloatBuffer", true, false));
+    typeMapping.put(new CType("GLint", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLint", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLuint", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLuint", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLshort", true, true),
+            new JType("java.nio.ShortBuffer", true, false));
+
+    // Typed pointers map to arrays + offsets
+    arrayTypeMapping.put(new CType("GLboolean", false, true),
+                 new JType("boolean", false, true));
+    arrayTypeMapping.put(new CType("GLfixed", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLfixed", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLfloat", false, true), new JType("float", false, true));
+    arrayTypeMapping.put(new CType("GLfloat", true, true), new JType("float", false, true));
+    arrayTypeMapping.put(new CType("GLint", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLint", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLshort", true, true), new JType("short", false, true));
+    arrayTypeMapping.put(new CType("GLuint", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLuint", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLintptr"), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLsizeiptr"), new JType("int", false, true));
+    }
+
+    public JType() {
+    }
+
+    public JType(String primitiveTypeName) {
+    this.baseType = primitiveTypeName;
+    this.isClass = false;
+    this.isArray = false;
+    }
+
+    public JType(String primitiveTypeName, boolean isClass, boolean isArray) {
+    this.baseType = primitiveTypeName;
+    this.isClass = isClass;
+    this.isArray = isArray;
+    }
+
+    public String getBaseType() {
+    return baseType;
+    }
+
+    @Override
+    public String toString() {
+    return baseType + (isArray ? "[]" : "");
+    }
+
+    public boolean isArray() {
+    return isArray;
+    }
+
+    public boolean isClass() {
+    return isClass;
+    }
+
+    public boolean isPrimitive() {
+    return !isClass() && !isArray();
+    }
+
+    public boolean isVoid() {
+    return baseType.equals("void");
+    }
+
+    public boolean isBuffer() {
+    return baseType.indexOf("Buffer") != -1;
+    }
+
+    public boolean isTypedBuffer() {
+    return !baseType.equals("java.nio.Buffer") &&
+        (baseType.indexOf("Buffer") != -1);
+    }
+
+    public static JType convert(CType ctype, boolean useArray) {
+     JType javaType = null;
+     if (useArray) {
+         javaType = arrayTypeMapping.get(ctype);
+     }
+     if (javaType == null) {
+         javaType = typeMapping.get(ctype);
+     }
+     if (javaType == null) {
+         throw new RuntimeException("Unsupported C type: " + ctype);
+     }
+     return javaType;
+    }
+}
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 33b9a3e..ef0dbd0 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -1,99 +1,55 @@
 import java.io.PrintStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 
-/**
- * Emits a Java interface and Java & C implementation for a C function.
- *
- * <p> The Java interface will have Buffer and array variants for functions that
- * have a typed pointer argument.  The array variant will convert a single "<type> *data"
- * argument to a pair of arguments "<type>[] data, int offset".
- */
-public class JniCodeEmitter implements CodeEmitter {
+public class JniCodeEmitter {
 
-    // If true, use C++ style for calling through a JNIEnv *:
-    // env->Func(...)
-    // If false, use C style:
-    // (*env)->Func(env, ...)
     static final boolean mUseCPlusPlus = true;
-
-    boolean mUseContextPointer = true;
-
-    String mClassPathName;
-    
-    ParameterChecker mChecker;
-    PrintStream mJava10InterfaceStream;
-    PrintStream mJava10ExtInterfaceStream;
-    PrintStream mJava11InterfaceStream;
-    PrintStream mJava11ExtInterfaceStream;
-    PrintStream mJava11ExtPackInterfaceStream;
-    PrintStream mJavaImplStream;
-    PrintStream mCStream;
-
-    PrintStream mJavaInterfaceStream;
-
-    List<String> nativeRegistrations = new ArrayList<String>();
-
+    protected boolean mUseContextPointer = true;
+    protected boolean mUseStaticMethods = false;
+    protected String mClassPathName;
+    protected ParameterChecker mChecker;
+    protected List<String> nativeRegistrations = new ArrayList<String>();
     boolean needsExit;
-
-    static String indent = "    ";
-
+    protected static String indent = "    ";
     HashSet<String> mFunctionsEmitted = new HashSet<String>();
 
-    /**
-     * @param java10InterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 functions
-     * @param java10ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 extension functions
-     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions 
-     * @param java11ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension functions
-     * @param java11ExtPackInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension Pack functions
-     * @param javaImplStream the PrintStream to which to emit the Java implementation
-     * @param cStream the PrintStream to which to emit the C implementation
-     */
-    public JniCodeEmitter(String classPathName,
-                          ParameterChecker checker,
-                          PrintStream java10InterfaceStream,
-                          PrintStream java10ExtInterfaceStream,
-                          PrintStream java11InterfaceStream,
-                          PrintStream java11ExtInterfaceStream,
-                          PrintStream java11ExtPackInterfaceStream,
-                          PrintStream javaImplStream,
-                          PrintStream cStream,
-                          boolean useContextPointer) {
-        mClassPathName = classPathName;
-        mChecker = checker;
-        mJava10InterfaceStream = java10InterfaceStream;
-        mJava10ExtInterfaceStream = java10ExtInterfaceStream;
-        mJava11InterfaceStream = java11InterfaceStream;
-        mJava11ExtInterfaceStream = java11ExtInterfaceStream;
-        mJava11ExtPackInterfaceStream = java11ExtPackInterfaceStream;
-        mJavaImplStream = javaImplStream;
-        mCStream = cStream;
-        mUseContextPointer = useContextPointer;
-    }
-
-    public void setVersion(int version, boolean ext, boolean pack) {
-        if (version == 0) {
-            mJavaInterfaceStream = ext ? mJava10ExtInterfaceStream :
-                mJava10InterfaceStream;
-        } else if (version == 1) {
-            mJavaInterfaceStream = ext ?
-                (pack ? mJava11ExtPackInterfaceStream :
-                 mJava11ExtInterfaceStream) :
-                mJava11InterfaceStream;
-        } else {
-            throw new RuntimeException("Bad version: " + version);
+    public static String getJniName(JType jType) {
+        String jniName = "";
+        if (jType.isClass()) {
+            return "L" + jType.getBaseType() + ";";
+        } else if (jType.isArray()) {
+            jniName = "[";
         }
+
+        String baseType = jType.getBaseType();
+        if (baseType.equals("int")) {
+            jniName += "I";
+        } else if (baseType.equals("float")) {
+            jniName += "F";
+        } else if (baseType.equals("boolean")) {
+            jniName += "Z";
+        } else if (baseType.equals("short")) {
+            jniName += "S";
+        } else if (baseType.equals("long")) {
+            jniName += "L";
+        } else if (baseType.equals("byte")) {
+            jniName += "B";
+        }
+        return jniName;
     }
 
-    public void emitCode(CFunc cfunc, String original) {
+
+    public void emitCode(CFunc cfunc, String original,
+            PrintStream javaInterfaceStream,
+            PrintStream javaImplStream,
+            PrintStream cStream) {
         JFunc jfunc;
         String signature;
         boolean duplicate;
-        
+
         if (cfunc.hasTypedPointerArg()) {
             jfunc = JFunc.convert(cfunc, true);
 
@@ -109,12 +65,14 @@
             }
 
             if (!duplicate) {
-                emitNativeDeclaration(jfunc, mJavaImplStream);
-                emitJavaCode(jfunc, mJavaImplStream);
+                emitNativeDeclaration(jfunc, javaImplStream);
+                emitJavaCode(jfunc, javaImplStream);
             }
-            emitJavaInterfaceCode(jfunc, mJavaInterfaceStream);
+            if (javaInterfaceStream != null) {
+                emitJavaInterfaceCode(jfunc, javaInterfaceStream);
+            }
             if (!duplicate) {
-                emitJniCode(jfunc, mCStream);
+                emitJniCode(jfunc, cStream);
             }
         }
 
@@ -129,12 +87,14 @@
         }
 
         if (!duplicate) {
-            emitNativeDeclaration(jfunc, mJavaImplStream);
+            emitNativeDeclaration(jfunc, javaImplStream);
         }
-        emitJavaInterfaceCode(jfunc, mJavaInterfaceStream);
+        if (javaInterfaceStream != null) {
+            emitJavaInterfaceCode(jfunc, javaInterfaceStream);
+        }
         if (!duplicate) {
-            emitJavaCode(jfunc, mJavaImplStream);
-            emitJniCode(jfunc, mCStream);
+            emitJavaCode(jfunc, javaImplStream);
+            emitJniCode(jfunc, cStream);
         }
     }
 
@@ -152,8 +112,8 @@
     public void emitJavaCode(JFunc jfunc, PrintStream out) {
         emitFunction(jfunc, out, false, false);
     }
-    
-    void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray ) {
+
+    void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray) {
         boolean isVoid = jfunc.getType().isVoid();
         boolean isPointerFunc = jfunc.getName().endsWith("Pointer") &&
             jfunc.getCFunc().hasPointerArg();
@@ -167,7 +127,7 @@
                     jfunc.getName() +
                     (isPointerFunc ? "Bounds" : "" ) +
                     "(");
-	
+
         int numArgs = jfunc.getNumArgs();
         for (int i = 0; i < numArgs; i++) {
             String argName = jfunc.getArgName(i);
@@ -177,7 +137,7 @@
                 String typeName = argType.getBaseType();
                 typeName = typeName.substring(9, typeName.length() - 6);
                 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
-                out.print(iii + indent + "getOffset(" + argName + ")"); 
+                out.print(iii + indent + "getOffset(" + argName + ")");
             } else {
                 out.print(iii + indent + argName);
             }
@@ -192,41 +152,40 @@
                 out.println(",");
             }
         }
-	
+
         out.println(iii + ");");
     }
 
-    void printIfcheckPostamble(PrintStream out, boolean isBuffer,
-                               boolean emitExceptionCheck, String iii) {
-        printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
-                              "offset", "_remaining", iii);
-    }
+    void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
+            String iii) {
+                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
+                                      "offset", "_remaining", iii);
+            }
 
-    void printIfcheckPostamble(PrintStream out, boolean isBuffer,
-                               boolean emitExceptionCheck,
-                               String offset, String remaining, String iii) {
-        out.println(iii + "    default:");
-        out.println(iii + "        _needed = 0;");
-        out.println(iii + "        break;");
-        out.println(iii + "}");
+    void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
+            String offset, String remaining, String iii) {
+                out.println(iii + "    default:");
+                out.println(iii + "        _needed = 0;");
+                out.println(iii + "        break;");
+                out.println(iii + "}");
 
-        out.println(iii + "if (" + remaining + " < _needed) {");
-        if (emitExceptionCheck) {
-            out.println(iii + indent + "_exception = 1;");
-        }
-        out.println(iii + indent +
-                    (mUseCPlusPlus ? "_env" : "(*_env)") +
-                    "->ThrowNew(" +
-                    (mUseCPlusPlus ? "" : "_env, ") +
-                    "IAEClass, " +
-                    "\"" +
-                    (isBuffer ? 
-                     "remaining()" : "length - " + offset) +
-                    " < needed\");");
-        out.println(iii + indent + "goto exit;");
-        needsExit = true;
-        out.println(iii + "}");
-    }
+                out.println(iii + "if (" + remaining + " < _needed) {");
+                if (emitExceptionCheck) {
+                    out.println(iii + indent + "_exception = 1;");
+                }
+                out.println(iii + indent +
+                            (mUseCPlusPlus ? "_env" : "(*_env)") +
+                            "->ThrowNew(" +
+                            (mUseCPlusPlus ? "" : "_env, ") +
+                            "IAEClass, " +
+                            "\"" +
+                            (isBuffer ?
+                             "remaining()" : "length - " + offset) +
+                            " < needed\");");
+                out.println(iii + indent + "goto exit;");
+                needsExit = true;
+                out.println(iii + "}");
+            }
 
     boolean isNullAllowed(CFunc cfunc) {
         String[] checks = mChecker.getChecks(cfunc.getName());
@@ -312,115 +271,106 @@
     }
 
     void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
-                                boolean isBuffer, boolean emitExceptionCheck,
-                                String offset, String remaining, String iii) {
-        CType returnType = cfunc.getType();
-        boolean isVoid = returnType.isVoid();
+            boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
 
-        String[] checks = mChecker.getChecks(cfunc.getName());
-        String checkVar;
-        String retval = getErrorReturnValue(cfunc);
+                String[] checks = mChecker.getChecks(cfunc.getName());
 
-        boolean lastWasIfcheck = false;
+                boolean lastWasIfcheck = false;
 
-        int index = 1;
-        if (checks != null) {
-            boolean remainingDeclared = false;
-            boolean nullCheckDeclared = false;
-            boolean offsetChecked = false;
-            while (index < checks.length) {
-                if (checks[index].startsWith("check")) {
-                    if (lastWasIfcheck) {
-                        printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
-                                              offset, remaining, iii);
+                int index = 1;
+                if (checks != null) {
+                    while (index < checks.length) {
+                        if (checks[index].startsWith("check")) {
+                            if (lastWasIfcheck) {
+                                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
+                                                      offset, remaining, iii);
+                            }
+                            lastWasIfcheck = false;
+                            if (cname != null && !cname.equals(checks[index + 1])) {
+                                index += 3;
+                                continue;
+                            }
+                            out.println(iii + "if (" + remaining + " < " +
+                                        checks[index + 2] +
+                                        ") {");
+                            if (emitExceptionCheck) {
+                                out.println(iii + indent + "_exception = 1;");
+                            }
+                    String exceptionClassName = "IAEClass";
+                    // If the "check" keyword was of the form
+                    // "check_<class name>", use the class name in the
+                    // exception to be thrown
+                    int underscore = checks[index].indexOf('_');
+                    if (underscore >= 0) {
+                    exceptionClassName = checks[index].substring(underscore + 1) + "Class";
                     }
-                    lastWasIfcheck = false;
-                    if (cname != null && !cname.equals(checks[index + 1])) {
-                        index += 3;
-                        continue;
-                    }
-                    out.println(iii + "if (" + remaining + " < " +
-                                checks[index + 2] +
-                                ") {");
-                    if (emitExceptionCheck) {
-                        out.println(iii + indent + "_exception = 1;");
-                    }
-		    String exceptionClassName = "IAEClass";
-		    // If the "check" keyword was of the form
-		    // "check_<class name>", use the class name in the
-		    // exception to be thrown
-		    int underscore = checks[index].indexOf('_');
-		    if (underscore >= 0) {
-			exceptionClassName = checks[index].substring(underscore + 1) + "Class";
-		    }
-                    out.println(iii + indent +
-                                (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                "->ThrowNew(" +
-                                (mUseCPlusPlus ? "" : "_env, ") +
-				exceptionClassName + ", " +
-                                "\"" +
-                                (isBuffer ? 
-                                 "remaining()" : "length - " + offset) +
-                                " < " + checks[index + 2] +
-                                "\");");
+                            out.println(iii + indent +
+                                        (mUseCPlusPlus ? "_env" : "(*_env)") +
+                                        "->ThrowNew(" +
+                                        (mUseCPlusPlus ? "" : "_env, ") +
+                        exceptionClassName + ", " +
+                                        "\"" +
+                                        (isBuffer ?
+                                         "remaining()" : "length - " + offset) +
+                                        " < " + checks[index + 2] +
+                                        "\");");
 
-                    out.println(iii + indent + "goto exit;");
-                    needsExit = true;
-                    out.println(iii + "}");
-                
-                    index += 3;
-                } else if (checks[index].equals("ifcheck")) {
-                    String[] matches = checks[index + 4].split(",");
+                            out.println(iii + indent + "goto exit;");
+                            needsExit = true;
+                            out.println(iii + "}");
 
-                    if (!lastWasIfcheck) {
-                        out.println(iii + "int _needed;");
-                        out.println(iii +
-                                    "switch (" +
-                                    checks[index + 3] +
-                                    ") {");
+                            index += 3;
+                        } else if (checks[index].equals("ifcheck")) {
+                            String[] matches = checks[index + 4].split(",");
+
+                            if (!lastWasIfcheck) {
+                                out.println(iii + "int _needed;");
+                                out.println(iii +
+                                            "switch (" +
+                                            checks[index + 3] +
+                                            ") {");
+                            }
+
+                            for (int i = 0; i < matches.length; i++) {
+                                out.println("#if defined(" + matches[i] + ")");
+                                out.println(iii +
+                                            "    case " +
+                                            matches[i] +
+                                            ":");
+                                out.println("#endif // defined(" + matches[i] + ")");
+                            }
+                            out.println(iii +
+                                        "        _needed = " +
+                                        checks[index + 2] +
+                                        ";");
+                            out.println(iii +
+                                        "        break;");
+
+                            lastWasIfcheck = true;
+                            index += 5;
+                        } else if (checks[index].equals("return")) {
+                            // ignore
+                            index += 2;
+                        } else if (checks[index].equals("unsupported")) {
+                            // ignore
+                            index += 1;
+                        } else if (checks[index].equals("nullAllowed")) {
+                            // ignore
+                            index += 1;
+                        } else {
+                            System.out.println("Error: unknown keyword \"" +
+                                               checks[index] + "\"");
+                            System.exit(0);
+                        }
                     }
-                    
-                    for (int i = 0; i < matches.length; i++) {
-                        out.println("#if defined(" + matches[i] + ")");
-                        out.println(iii +
-                                    "    case " +
-                                    matches[i] +
-                                    ":");
-                        out.println("#endif // defined(" + matches[i] + ")");
-                    }
-                    out.println(iii +
-                                "        _needed = " +
-                                checks[index + 2] +
-                                ";");
-                    out.println(iii +
-                                "        break;");
-                
-                    lastWasIfcheck = true;
-                    index += 5;
-                } else if (checks[index].equals("return")) {
-                    // ignore
-                    index += 2;
-                } else if (checks[index].equals("unsupported")) {
-                    // ignore
-                    index += 1;
-                } else if (checks[index].equals("nullAllowed")) {
-                    // ignore
-                    index += 1;
-                } else {
-                    System.out.println("Error: unknown keyword \"" +
-                                       checks[index] + "\"");
-                    System.exit(0);
+                }
+
+                if (lastWasIfcheck) {
+                    printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
                 }
             }
-        }
 
-        if (lastWasIfcheck) {
-            printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
-        }
-    }
-
-    boolean hasNonConstArg(JFunc jfunc, CFunc cfunc,
-        List<Integer> nonPrimitiveArgs) {
+    boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
         if (nonPrimitiveArgs.size() > 0) {
             for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
                 int idx = nonPrimitiveArgs.get(i).intValue();
@@ -439,7 +389,7 @@
 
         return false;
     }
-    
+
     /**
      * Emit a function in several variants:
      *
@@ -449,9 +399,7 @@
      *   if interfaceDecl:  public <returntype> func(args);
      *   if !interfaceDecl: public <returntype> func(args) { body }
      */
-    void emitFunction(JFunc jfunc,
-                      PrintStream out,
-                      boolean nativeDecl, boolean interfaceDecl) {
+    void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
         boolean isPointerFunc =
             jfunc.getName().endsWith("Pointer") &&
             jfunc.getCFunc().hasPointerArg();
@@ -462,28 +410,30 @@
             return;
         }
 
+        String maybeStatic = mUseStaticMethods ? "static " : "";
+
         if (isPointerFunc) {
             out.println(indent +
-                        (nativeDecl ? "private native " :
-                         (interfaceDecl ? "" : "public ")) +
+                        (nativeDecl ? "private " + maybeStatic +"native " :
+                         (interfaceDecl ? "" : "public ") + maybeStatic) +
                         jfunc.getType() + " " +
                         jfunc.getName() +
                         (nativeDecl ? "Bounds" : "") +
                         "(");
         } else {
             out.println(indent +
-                        (nativeDecl ? "public native " :
-                         (interfaceDecl ? "" : "public ")) +
+                        (nativeDecl ? "public " + maybeStatic +"native " :
+                         (interfaceDecl ? "" : "public ") + maybeStatic) +
                         jfunc.getType() + " " +
                         jfunc.getName() +
                         "(");
         }
-	
+
         int numArgs = jfunc.getNumArgs();
         for (int i = 0; i < numArgs; i++) {
             String argName = jfunc.getArgName(i);
             JType argType = jfunc.getArgType(i);
-	    
+
             out.print(indent + indent + argType + " " + argName);
             if (i == numArgs - 1) {
                 if (isPointerFunc && nativeDecl) {
@@ -561,29 +511,44 @@
         out.println();
     }
 
-    public static String getJniName(JType jType) {
-        String jniName = "";
-        if (jType.isClass()) {
-            return "L" + jType.getBaseType() + ";";
-        } else if (jType.isArray()) {
-            jniName = "[";
+    public void addNativeRegistration(String s) {
+        nativeRegistrations.add(s);
+    }
+
+    public void emitNativeRegistration(String registrationFunctionName,
+            PrintStream cStream) {
+        cStream.println("static const char *classPathName = \"" +
+                        mClassPathName +
+                        "\";");
+        cStream.println();
+
+        cStream.println("static JNINativeMethod methods[] = {");
+
+        cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
+
+        Iterator<String> i = nativeRegistrations.iterator();
+        while (i.hasNext()) {
+            cStream.println(i.next());
         }
-	
-        String baseType = jType.getBaseType();
-        if (baseType.equals("int")) {
-            jniName += "I";
-        } else if (baseType.equals("float")) {
-            jniName += "F";
-        } else if (baseType.equals("boolean")) {
-            jniName += "Z";
-        } else if (baseType.equals("short")) {
-            jniName += "S";
-        } else if (baseType.equals("long")) {
-            jniName += "L";
-        } else if (baseType.equals("byte")) {
-            jniName += "B";
-        }
-        return jniName;
+
+        cStream.println("};");
+        cStream.println();
+
+
+        cStream.println("int " + registrationFunctionName + "(JNIEnv *_env)");
+        cStream.println("{");
+        cStream.println(indent +
+                        "int err;");
+
+        cStream.println(indent +
+                        "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
+
+        cStream.println(indent + "return err;");
+        cStream.println("}");
+    }
+
+    public JniCodeEmitter() {
+        super();
     }
 
     String getJniType(JType jType) {
@@ -604,7 +569,7 @@
             return "jobject";
         }
     }
-    
+
     String getJniMangledName(String name) {
         name = name.replaceAll("_", "_1");
         name = name.replaceAll(";", "_2");
@@ -614,7 +579,7 @@
 
     public void emitJniCode(JFunc jfunc, PrintStream out) {
         CFunc cfunc = jfunc.getCFunc();
-	
+
         // Emit comment identifying original C function
         //
         // Example:
@@ -658,13 +623,13 @@
         }
 
         // Append signature to function name
-        String sig = getJniMangledName(signature).replace('.', '_');        
+        String sig = getJniMangledName(signature).replace('.', '_');
         out.print("__" + sig);
         outName += "__" + sig;
-	
+
         signature = signature.replace('.', '/');
         rsignature = rsignature.replace('.', '/');
-	
+
         out.println();
         if (rsignature.length() == 0) {
             rsignature = "V";
@@ -718,13 +683,11 @@
             out.print(", jint remaining");
         }
         out.println(") {");
-	
+
         int numArrays = 0;
         int numBuffers = 0;
         for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
             int idx = nonPrimitiveArgs.get(i).intValue();
-            int cIndex = jfunc.getArgCIndex(idx);
-            String cname = cfunc.getArgName(cIndex);
             if (jfunc.getArgType(idx).isArray()) {
                 ++numArrays;
             }
@@ -740,7 +703,7 @@
         // Example:
         //
         // android::gl::ogles_context_t *ctx;
-        // 
+        //
         // jint _exception;
         // GLenum _returnValue;
         //
@@ -827,15 +790,13 @@
                 out.println(indent +
                             decl +
                             (decl.endsWith("*") ? "" : " ") +
-                            jfunc.getArgName(idx) + 
+                            jfunc.getArgName(idx) +
                             " = (" + decl + ") 0;");
             }
 
             out.println();
         }
 
-        String retval = isVoid ? "" : " _returnValue";
-
         // Emit 'GetPrimitiveArrayCritical' for arrays
         // Emit 'GetPointer' calls for Buffer pointers
         int bufArgIdx = 0;
@@ -843,7 +804,7 @@
             for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
                 int idx = nonPrimitiveArgs.get(i).intValue();
                 int cIndex = jfunc.getArgCIndex(idx);
-		
+
                 String cname = cfunc.getArgName(cIndex);
                 offset = numArrays <= 1 ? "offset" :
                     cname + "Offset";
@@ -852,7 +813,7 @@
 
                 if (jfunc.getArgType(idx).isArray()) {
                     out.println(indent +
-                                "if (!" + 
+                                "if (!" +
                                 cname +
                                 "_ref) {");
                     if (emitExceptionCheck) {
@@ -884,7 +845,7 @@
                     out.println(indent + "}");
 
                     out.println(indent + remaining + " = " +
-                                    (mUseCPlusPlus ? "_env" : "(*_env)") + 
+                                    (mUseCPlusPlus ? "_env" : "(*_env)") +
                                     "->GetArrayLength(" +
                                     (mUseCPlusPlus ? "" : "_env, ") +
                                     cname + "_ref) - " + offset + ";");
@@ -901,7 +862,7 @@
                     out.println(indent + "    " +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->GetPrimitiveArrayCritical(" +
-                                (mUseCPlusPlus ? "" : "_env, ") + 
+                                (mUseCPlusPlus ? "" : "_env, ") +
                                 jfunc.getArgName(idx) +
                                 "_ref, (jboolean *)0);");
                     out.println(indent +
@@ -917,7 +878,7 @@
                         out.println(indent + "if (" + cname + "_buf) {");
                         out.print(indent);
                     }
-                    
+
                     out.println(indent +
                                 cname +
                                 " = (" +
@@ -950,10 +911,10 @@
                 name.substring(1, name.length());
             out.print("ctx->procs.");
         }
-        
+
         out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
 
-        numArgs = cfunc.getNumArgs();    
+        numArgs = cfunc.getNumArgs();
         if (numArgs == 0) {
             if (mUseContextPointer) {
                 out.println("ctx);");
@@ -1006,7 +967,7 @@
 
                 int cIndex = jfunc.getArgCIndex(idx);
                 if (jfunc.getArgType(idx).isArray()) {
-		    
+
                     // If the argument is 'const', GL will not write to it.
                     // In this case, we can use the 'JNI_ABORT' flag to avoid
                     // the need to write back to the Java array
@@ -1015,7 +976,7 @@
                     out.println(indent + indent +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->ReleasePrimitiveArrayCritical(" +
-                                (mUseCPlusPlus ? "" : "_env, ") + 
+                                (mUseCPlusPlus ? "" : "_env, ") +
                                 jfunc.getArgName(idx) + "_ref, " +
                                 cfunc.getArgName(cIndex) +
                                 "_base,");
@@ -1049,38 +1010,4 @@
         out.println();
     }
 
-    public void addNativeRegistration(String s) {
-        nativeRegistrations.add(s);
-    }
-
-    public void emitNativeRegistration() {
-        mCStream.println("static const char *classPathName = \"" +
-                        mClassPathName +
-                        "\";");
-        mCStream.println();
-
-        mCStream.println("static JNINativeMethod methods[] = {");
-
-        mCStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
-
-        Iterator<String> i = nativeRegistrations.iterator();
-        while (i.hasNext()) {
-            mCStream.println(i.next());
-        }
-
-        mCStream.println("};");
-        mCStream.println();
-    
-
-        mCStream.println("int register_com_google_android_gles_jni_GLImpl(JNIEnv *_env)");
-        mCStream.println("{");
-        mCStream.println(indent +
-                        "int err;");
-
-        mCStream.println(indent +
-                        "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");
-
-        mCStream.println(indent + "return err;");
-        mCStream.println("}");
-    }
 }
diff --git a/opengl/tools/glgen/src/Jsr239CodeEmitter.java b/opengl/tools/glgen/src/Jsr239CodeEmitter.java
new file mode 100644
index 0000000..335d226
--- /dev/null
+++ b/opengl/tools/glgen/src/Jsr239CodeEmitter.java
@@ -0,0 +1,74 @@
+import java.io.PrintStream;
+
+/**
+ * Emits a Java interface and Java & C implementation for a C function.
+ *
+ * <p> The Java interface will have Buffer and array variants for functions that
+ * have a typed pointer argument.  The array variant will convert a single "<type> *data"
+ * argument to a pair of arguments "<type>[] data, int offset".
+ */
+public class Jsr239CodeEmitter extends JniCodeEmitter implements CodeEmitter {
+
+    PrintStream mJava10InterfaceStream;
+    PrintStream mJava10ExtInterfaceStream;
+    PrintStream mJava11InterfaceStream;
+    PrintStream mJava11ExtInterfaceStream;
+    PrintStream mJava11ExtPackInterfaceStream;
+    PrintStream mJavaImplStream;
+    PrintStream mCStream;
+
+    PrintStream mJavaInterfaceStream;
+
+    /**
+     * @param java10InterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 functions
+     * @param java10ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 extension functions
+     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions
+     * @param java11ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension functions
+     * @param java11ExtPackInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension Pack functions
+     * @param javaImplStream the PrintStream to which to emit the Java implementation
+     * @param cStream the PrintStream to which to emit the C implementation
+     */
+    public Jsr239CodeEmitter(String classPathName,
+                          ParameterChecker checker,
+                          PrintStream java10InterfaceStream,
+                          PrintStream java10ExtInterfaceStream,
+                          PrintStream java11InterfaceStream,
+                          PrintStream java11ExtInterfaceStream,
+                          PrintStream java11ExtPackInterfaceStream,
+                          PrintStream javaImplStream,
+                          PrintStream cStream,
+                          boolean useContextPointer) {
+        mClassPathName = classPathName;
+        mChecker = checker;
+        mJava10InterfaceStream = java10InterfaceStream;
+        mJava10ExtInterfaceStream = java10ExtInterfaceStream;
+        mJava11InterfaceStream = java11InterfaceStream;
+        mJava11ExtInterfaceStream = java11ExtInterfaceStream;
+        mJava11ExtPackInterfaceStream = java11ExtPackInterfaceStream;
+        mJavaImplStream = javaImplStream;
+        mCStream = cStream;
+        mUseContextPointer = useContextPointer;
+    }
+
+    public void setVersion(int version, boolean ext, boolean pack) {
+        if (version == 0) {
+            mJavaInterfaceStream = ext ? mJava10ExtInterfaceStream :
+                mJava10InterfaceStream;
+        } else if (version == 1) {
+            mJavaInterfaceStream = ext ?
+                (pack ? mJava11ExtPackInterfaceStream :
+                 mJava11ExtInterfaceStream) :
+                mJava11InterfaceStream;
+        } else {
+            throw new RuntimeException("Bad version: " + version);
+        }
+    }
+
+    public void emitCode(CFunc cfunc, String original) {
+        emitCode(cfunc, original, mJavaInterfaceStream, mJavaImplStream, mCStream);
+    }
+
+    public void emitNativeRegistration() {
+        emitNativeRegistration("register_com_google_android_gles_jni_GLImpl", mCStream);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl b/opengl/tools/glgen/stubs/gles11/GLES10ExtHeader.java-if
similarity index 67%
copy from telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl
copy to opengl/tools/glgen/stubs/gles11/GLES10ExtHeader.java-if
index 68d9a7c..42891ea 100644
--- a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtHeader.java-if
@@ -1,5 +1,5 @@
-/*
-** Copyright 2007, The Android Open Source Project
+**
+** 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.
@@ -10,10 +10,17 @@
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
+** See the License for the specific language governing permissions and 
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+// This source file is automatically generated
 
-parcelable AdnRecord;
+package android.opengl;
+
+public class GLES10Ext {
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+    
\ No newline at end of file
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
similarity index 97%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index 6495686..3e5c19c 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -44,7 +44,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10Header.java-if b/opengl/tools/glgen/stubs/gles11/GLES10Header.java-if
new file mode 100644
index 0000000..4b2a831
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES10Header.java-if
@@ -0,0 +1,271 @@
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import java.nio.Buffer;
+
+public class GLES10 {
+    public static final int GL_ADD                                   = 0x0104;
+    public static final int GL_ALIASED_LINE_WIDTH_RANGE              = 0x846E;
+    public static final int GL_ALIASED_POINT_SIZE_RANGE              = 0x846D;
+    public static final int GL_ALPHA                                 = 0x1906;
+    public static final int GL_ALPHA_BITS                            = 0x0D55;
+    public static final int GL_ALPHA_TEST                            = 0x0BC0;
+    public static final int GL_ALWAYS                                = 0x0207;
+    public static final int GL_AMBIENT                               = 0x1200;
+    public static final int GL_AMBIENT_AND_DIFFUSE                   = 0x1602;
+    public static final int GL_AND                                   = 0x1501;
+    public static final int GL_AND_INVERTED                          = 0x1504;
+    public static final int GL_AND_REVERSE                           = 0x1502;
+    public static final int GL_BACK                                  = 0x0405;
+    public static final int GL_BLEND                                 = 0x0BE2;
+    public static final int GL_BLUE_BITS                             = 0x0D54;
+    public static final int GL_BYTE                                  = 0x1400;
+    public static final int GL_CCW                                   = 0x0901;
+    public static final int GL_CLAMP_TO_EDGE                         = 0x812F;
+    public static final int GL_CLEAR                                 = 0x1500;
+    public static final int GL_COLOR_ARRAY                           = 0x8076;
+    public static final int GL_COLOR_BUFFER_BIT                      = 0x4000;
+    public static final int GL_COLOR_LOGIC_OP                        = 0x0BF2;
+    public static final int GL_COLOR_MATERIAL                        = 0x0B57;
+    public static final int GL_COMPRESSED_TEXTURE_FORMATS            = 0x86A3;
+    public static final int GL_CONSTANT_ATTENUATION                  = 0x1207;
+    public static final int GL_COPY                                  = 0x1503;
+    public static final int GL_COPY_INVERTED                         = 0x150C;
+    public static final int GL_CULL_FACE                             = 0x0B44;
+    public static final int GL_CW                                    = 0x0900;
+    public static final int GL_DECAL                                 = 0x2101;
+    public static final int GL_DECR                                  = 0x1E03;
+    public static final int GL_DEPTH_BITS                            = 0x0D56;
+    public static final int GL_DEPTH_BUFFER_BIT                      = 0x0100;
+    public static final int GL_DEPTH_TEST                            = 0x0B71;
+    public static final int GL_DIFFUSE                               = 0x1201;
+    public static final int GL_DITHER                                = 0x0BD0;
+    public static final int GL_DONT_CARE                             = 0x1100;
+    public static final int GL_DST_ALPHA                             = 0x0304;
+    public static final int GL_DST_COLOR                             = 0x0306;
+    public static final int GL_EMISSION                              = 0x1600;
+    public static final int GL_EQUAL                                 = 0x0202;
+    public static final int GL_EQUIV                                 = 0x1509;
+    public static final int GL_EXP                                   = 0x0800;
+    public static final int GL_EXP2                                  = 0x0801;
+    public static final int GL_EXTENSIONS                            = 0x1F03;
+    public static final int GL_FALSE                                 = 0;
+    public static final int GL_FASTEST                               = 0x1101;
+    public static final int GL_FIXED                                 = 0x140C;
+    public static final int GL_FLAT                                  = 0x1D00;
+    public static final int GL_FLOAT                                 = 0x1406;
+    public static final int GL_FOG                                   = 0x0B60;
+    public static final int GL_FOG_COLOR                             = 0x0B66;
+    public static final int GL_FOG_DENSITY                           = 0x0B62;
+    public static final int GL_FOG_END                               = 0x0B64;
+    public static final int GL_FOG_HINT                              = 0x0C54;
+    public static final int GL_FOG_MODE                              = 0x0B65;
+    public static final int GL_FOG_START                             = 0x0B63;
+    public static final int GL_FRONT                                 = 0x0404;
+    public static final int GL_FRONT_AND_BACK                        = 0x0408;
+    public static final int GL_GEQUAL                                = 0x0206;
+    public static final int GL_GREATER                               = 0x0204;
+    public static final int GL_GREEN_BITS                            = 0x0D53;
+    public static final int GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES  = 0x8B9B;
+    public static final int GL_IMPLEMENTATION_COLOR_READ_TYPE_OES    = 0x8B9A;
+    public static final int GL_INCR                                  = 0x1E02;
+    public static final int GL_INVALID_ENUM                          = 0x0500;
+    public static final int GL_INVALID_OPERATION                     = 0x0502;
+    public static final int GL_INVALID_VALUE                         = 0x0501;
+    public static final int GL_INVERT                                = 0x150A;
+    public static final int GL_KEEP                                  = 0x1E00;
+    public static final int GL_LEQUAL                                = 0x0203;
+    public static final int GL_LESS                                  = 0x0201;
+    public static final int GL_LIGHT_MODEL_AMBIENT                   = 0x0B53;
+    public static final int GL_LIGHT_MODEL_TWO_SIDE                  = 0x0B52;
+    public static final int GL_LIGHT0                                = 0x4000;
+    public static final int GL_LIGHT1                                = 0x4001;
+    public static final int GL_LIGHT2                                = 0x4002;
+    public static final int GL_LIGHT3                                = 0x4003;
+    public static final int GL_LIGHT4                                = 0x4004;
+    public static final int GL_LIGHT5                                = 0x4005;
+    public static final int GL_LIGHT6                                = 0x4006;
+    public static final int GL_LIGHT7                                = 0x4007;
+    public static final int GL_LIGHTING                              = 0x0B50;
+    public static final int GL_LINE_LOOP                             = 0x0002;
+    public static final int GL_LINE_SMOOTH                           = 0x0B20;
+    public static final int GL_LINE_SMOOTH_HINT                      = 0x0C52;
+    public static final int GL_LINE_STRIP                            = 0x0003;
+    public static final int GL_LINEAR                                = 0x2601;
+    public static final int GL_LINEAR_ATTENUATION                    = 0x1208;
+    public static final int GL_LINEAR_MIPMAP_LINEAR                  = 0x2703;
+    public static final int GL_LINEAR_MIPMAP_NEAREST                 = 0x2701;
+    public static final int GL_LINES                                 = 0x0001;
+    public static final int GL_LUMINANCE                             = 0x1909;
+    public static final int GL_LUMINANCE_ALPHA                       = 0x190A;
+    public static final int GL_MAX_ELEMENTS_INDICES                  = 0x80E9;
+    public static final int GL_MAX_ELEMENTS_VERTICES                 = 0x80E8;
+    public static final int GL_MAX_LIGHTS                            = 0x0D31;
+    public static final int GL_MAX_MODELVIEW_STACK_DEPTH             = 0x0D36;
+    public static final int GL_MAX_PROJECTION_STACK_DEPTH            = 0x0D38;
+    public static final int GL_MAX_TEXTURE_SIZE                      = 0x0D33;
+    public static final int GL_MAX_TEXTURE_STACK_DEPTH               = 0x0D39;
+    public static final int GL_MAX_TEXTURE_UNITS                     = 0x84E2;
+    public static final int GL_MAX_VIEWPORT_DIMS                     = 0x0D3A;
+    public static final int GL_MODELVIEW                             = 0x1700;
+    public static final int GL_MODULATE                              = 0x2100;
+    public static final int GL_MULTISAMPLE                           = 0x809D;
+    public static final int GL_NAND                                  = 0x150E;
+    public static final int GL_NEAREST                               = 0x2600;
+    public static final int GL_NEAREST_MIPMAP_LINEAR                 = 0x2702;
+    public static final int GL_NEAREST_MIPMAP_NEAREST                = 0x2700;
+    public static final int GL_NEVER                                 = 0x0200;
+    public static final int GL_NICEST                                = 0x1102;
+    public static final int GL_NO_ERROR                              = 0;
+    public static final int GL_NOOP                                  = 0x1505;
+    public static final int GL_NOR                                   = 0x1508;
+    public static final int GL_NORMAL_ARRAY                          = 0x8075;
+    public static final int GL_NORMALIZE                             = 0x0BA1;
+    public static final int GL_NOTEQUAL                              = 0x0205;
+    public static final int GL_NUM_COMPRESSED_TEXTURE_FORMATS        = 0x86A2;
+    public static final int GL_ONE                                   = 1;
+    public static final int GL_ONE_MINUS_DST_ALPHA                   = 0x0305;
+    public static final int GL_ONE_MINUS_DST_COLOR                   = 0x0307;
+    public static final int GL_ONE_MINUS_SRC_ALPHA                   = 0x0303;
+    public static final int GL_ONE_MINUS_SRC_COLOR                   = 0x0301;
+    public static final int GL_OR                                    = 0x1507;
+    public static final int GL_OR_INVERTED                           = 0x150D;
+    public static final int GL_OR_REVERSE                            = 0x150B;
+    public static final int GL_OUT_OF_MEMORY                         = 0x0505;
+    public static final int GL_PACK_ALIGNMENT                        = 0x0D05;
+    public static final int GL_PALETTE4_R5_G6_B5_OES                 = 0x8B92;
+    public static final int GL_PALETTE4_RGB5_A1_OES                  = 0x8B94;
+    public static final int GL_PALETTE4_RGB8_OES                     = 0x8B90;
+    public static final int GL_PALETTE4_RGBA4_OES                    = 0x8B93;
+    public static final int GL_PALETTE4_RGBA8_OES                    = 0x8B91;
+    public static final int GL_PALETTE8_R5_G6_B5_OES                 = 0x8B97;
+    public static final int GL_PALETTE8_RGB5_A1_OES                  = 0x8B99;
+    public static final int GL_PALETTE8_RGB8_OES                     = 0x8B95;
+    public static final int GL_PALETTE8_RGBA4_OES                    = 0x8B98;
+    public static final int GL_PALETTE8_RGBA8_OES                    = 0x8B96;
+    public static final int GL_PERSPECTIVE_CORRECTION_HINT           = 0x0C50;
+    public static final int GL_POINT_SMOOTH                          = 0x0B10;
+    public static final int GL_POINT_SMOOTH_HINT                     = 0x0C51;
+    public static final int GL_POINTS                                = 0x0000;
+    public static final int GL_POINT_FADE_THRESHOLD_SIZE             = 0x8128;
+    public static final int GL_POINT_SIZE                            = 0x0B11;
+    public static final int GL_POLYGON_OFFSET_FILL                   = 0x8037;
+    public static final int GL_POLYGON_SMOOTH_HINT                   = 0x0C53;
+    public static final int GL_POSITION                              = 0x1203;
+    public static final int GL_PROJECTION                            = 0x1701;
+    public static final int GL_QUADRATIC_ATTENUATION                 = 0x1209;
+    public static final int GL_RED_BITS                              = 0x0D52;
+    public static final int GL_RENDERER                              = 0x1F01;
+    public static final int GL_REPEAT                                = 0x2901;
+    public static final int GL_REPLACE                               = 0x1E01;
+    public static final int GL_RESCALE_NORMAL                        = 0x803A;
+    public static final int GL_RGB                                   = 0x1907;
+    public static final int GL_RGBA                                  = 0x1908;
+    public static final int GL_SAMPLE_ALPHA_TO_COVERAGE              = 0x809E;
+    public static final int GL_SAMPLE_ALPHA_TO_ONE                   = 0x809F;
+    public static final int GL_SAMPLE_COVERAGE                       = 0x80A0;
+    public static final int GL_SCISSOR_TEST                          = 0x0C11;
+    public static final int GL_SET                                   = 0x150F;
+    public static final int GL_SHININESS                             = 0x1601;
+    public static final int GL_SHORT                                 = 0x1402;
+    public static final int GL_SMOOTH                                = 0x1D01;
+    public static final int GL_SMOOTH_LINE_WIDTH_RANGE               = 0x0B22;
+    public static final int GL_SMOOTH_POINT_SIZE_RANGE               = 0x0B12;
+    public static final int GL_SPECULAR                              = 0x1202;
+    public static final int GL_SPOT_CUTOFF                           = 0x1206;
+    public static final int GL_SPOT_DIRECTION                        = 0x1204;
+    public static final int GL_SPOT_EXPONENT                         = 0x1205;
+    public static final int GL_SRC_ALPHA                             = 0x0302;
+    public static final int GL_SRC_ALPHA_SATURATE                    = 0x0308;
+    public static final int GL_SRC_COLOR                             = 0x0300;
+    public static final int GL_STACK_OVERFLOW                        = 0x0503;
+    public static final int GL_STACK_UNDERFLOW                       = 0x0504;
+    public static final int GL_STENCIL_BITS                          = 0x0D57;
+    public static final int GL_STENCIL_BUFFER_BIT                    = 0x0400;
+    public static final int GL_STENCIL_TEST                          = 0x0B90;
+    public static final int GL_SUBPIXEL_BITS                         = 0x0D50;
+    public static final int GL_TEXTURE                               = 0x1702;
+    public static final int GL_TEXTURE_2D                            = 0x0DE1;
+    public static final int GL_TEXTURE_COORD_ARRAY                   = 0x8078;
+    public static final int GL_TEXTURE_ENV                           = 0x2300;
+    public static final int GL_TEXTURE_ENV_COLOR                     = 0x2201;
+    public static final int GL_TEXTURE_ENV_MODE                      = 0x2200;
+    public static final int GL_TEXTURE_MAG_FILTER                    = 0x2800;
+    public static final int GL_TEXTURE_MIN_FILTER                    = 0x2801;
+    public static final int GL_TEXTURE_WRAP_S                        = 0x2802;
+    public static final int GL_TEXTURE_WRAP_T                        = 0x2803;
+    public static final int GL_TEXTURE0                              = 0x84C0;
+    public static final int GL_TEXTURE1                              = 0x84C1;
+    public static final int GL_TEXTURE2                              = 0x84C2;
+    public static final int GL_TEXTURE3                              = 0x84C3;
+    public static final int GL_TEXTURE4                              = 0x84C4;
+    public static final int GL_TEXTURE5                              = 0x84C5;
+    public static final int GL_TEXTURE6                              = 0x84C6;
+    public static final int GL_TEXTURE7                              = 0x84C7;
+    public static final int GL_TEXTURE8                              = 0x84C8;
+    public static final int GL_TEXTURE9                              = 0x84C9;
+    public static final int GL_TEXTURE10                             = 0x84CA;
+    public static final int GL_TEXTURE11                             = 0x84CB;
+    public static final int GL_TEXTURE12                             = 0x84CC;
+    public static final int GL_TEXTURE13                             = 0x84CD;
+    public static final int GL_TEXTURE14                             = 0x84CE;
+    public static final int GL_TEXTURE15                             = 0x84CF;
+    public static final int GL_TEXTURE16                             = 0x84D0;
+    public static final int GL_TEXTURE17                             = 0x84D1;
+    public static final int GL_TEXTURE18                             = 0x84D2;
+    public static final int GL_TEXTURE19                             = 0x84D3;
+    public static final int GL_TEXTURE20                             = 0x84D4;
+    public static final int GL_TEXTURE21                             = 0x84D5;
+    public static final int GL_TEXTURE22                             = 0x84D6;
+    public static final int GL_TEXTURE23                             = 0x84D7;
+    public static final int GL_TEXTURE24                             = 0x84D8;
+    public static final int GL_TEXTURE25                             = 0x84D9;
+    public static final int GL_TEXTURE26                             = 0x84DA;
+    public static final int GL_TEXTURE27                             = 0x84DB;
+    public static final int GL_TEXTURE28                             = 0x84DC;
+    public static final int GL_TEXTURE29                             = 0x84DD;
+    public static final int GL_TEXTURE30                             = 0x84DE;
+    public static final int GL_TEXTURE31                             = 0x84DF;
+    public static final int GL_TRIANGLE_FAN                          = 0x0006;
+    public static final int GL_TRIANGLE_STRIP                        = 0x0005;
+    public static final int GL_TRIANGLES                             = 0x0004;
+    public static final int GL_TRUE                                  = 1;
+    public static final int GL_UNPACK_ALIGNMENT                      = 0x0CF5;
+    public static final int GL_UNSIGNED_BYTE                         = 0x1401;
+    public static final int GL_UNSIGNED_SHORT                        = 0x1403;
+    public static final int GL_UNSIGNED_SHORT_4_4_4_4                = 0x8033;
+    public static final int GL_UNSIGNED_SHORT_5_5_5_1                = 0x8034;
+    public static final int GL_UNSIGNED_SHORT_5_6_5                  = 0x8363;
+    public static final int GL_VENDOR                                = 0x1F00;
+    public static final int GL_VERSION                               = 0x1F02;
+    public static final int GL_VERTEX_ARRAY                          = 0x8074;
+    public static final int GL_XOR                                   = 0x1506;
+    public static final int GL_ZERO                                  = 0;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+
+    private static Buffer _colorPointer;
+    private static Buffer _normalPointer;
+    private static Buffer _texCoordPointer;
+    private static Buffer _vertexPointer;
+
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
similarity index 98%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index 6495686..3e5c19c 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -44,7 +44,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
new file mode 100644
index 0000000..428ccee
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtHeader.java-if
@@ -0,0 +1,130 @@
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+public class GLES11Ext {
+    public static final int GL_BLEND_EQUATION_RGB_OES                               = 0x8009;
+    public static final int GL_BLEND_EQUATION_ALPHA_OES                             = 0x883D;
+    public static final int GL_BLEND_DST_RGB_OES                                    = 0x80C8;
+    public static final int GL_BLEND_SRC_RGB_OES                                    = 0x80C9;
+    public static final int GL_BLEND_DST_ALPHA_OES                                  = 0x80CA;
+    public static final int GL_BLEND_SRC_ALPHA_OES                                  = 0x80CB;
+    public static final int GL_BLEND_EQUATION_OES                                   = 0x8009;
+    public static final int GL_FUNC_ADD_OES                                         = 0x8006;
+    public static final int GL_FUNC_SUBTRACT_OES                                    = 0x800A;
+    public static final int GL_FUNC_REVERSE_SUBTRACT_OES                            = 0x800B;
+    public static final int GL_ETC1_RGB8_OES                                        = 0x8D64;
+    public static final int GL_DEPTH_COMPONENT24_OES                                = 0x81A6;
+    public static final int GL_DEPTH_COMPONENT32_OES                                = 0x81A7;
+    public static final int GL_TEXTURE_CROP_RECT_OES                                = 0x8B9D;
+    public static final int GL_FIXED_OES                                            = 0x140C;
+    public static final int GL_NONE_OES                                             = 0;
+    public static final int GL_FRAMEBUFFER_OES                                      = 0x8D40;
+    public static final int GL_RENDERBUFFER_OES                                     = 0x8D41;
+    public static final int GL_RGBA4_OES                                            = 0x8056;
+    public static final int GL_RGB5_A1_OES                                          = 0x8057;
+    public static final int GL_RGB565_OES                                           = 0x8D62;
+    public static final int GL_DEPTH_COMPONENT16_OES                                = 0x81A5;
+    public static final int GL_RENDERBUFFER_WIDTH_OES                               = 0x8D42;
+    public static final int GL_RENDERBUFFER_HEIGHT_OES                              = 0x8D43;
+    public static final int GL_RENDERBUFFER_INTERNAL_FORMAT_OES                     = 0x8D44;
+    public static final int GL_RENDERBUFFER_RED_SIZE_OES                            = 0x8D50;
+    public static final int GL_RENDERBUFFER_GREEN_SIZE_OES                          = 0x8D51;
+    public static final int GL_RENDERBUFFER_BLUE_SIZE_OES                           = 0x8D52;
+    public static final int GL_RENDERBUFFER_ALPHA_SIZE_OES                          = 0x8D53;
+    public static final int GL_RENDERBUFFER_DEPTH_SIZE_OES                          = 0x8D54;
+    public static final int GL_RENDERBUFFER_STENCIL_SIZE_OES                        = 0x8D55;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES               = 0x8CD0;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES               = 0x8CD1;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES             = 0x8CD2;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES     = 0x8CD3;
+    public static final int GL_COLOR_ATTACHMENT0_OES                                = 0x8CE0;
+    public static final int GL_DEPTH_ATTACHMENT_OES                                 = 0x8D00;
+    public static final int GL_STENCIL_ATTACHMENT_OES                               = 0x8D20;
+    public static final int GL_FRAMEBUFFER_COMPLETE_OES                             = 0x8CD5;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES                = 0x8CD6;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES        = 0x8CD7;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES                = 0x8CD9;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES                   = 0x8CDA;
+    public static final int GL_FRAMEBUFFER_UNSUPPORTED_OES                          = 0x8CDD;
+    public static final int GL_FRAMEBUFFER_BINDING_OES                              = 0x8CA6;
+    public static final int GL_RENDERBUFFER_BINDING_OES                             = 0x8CA7;
+    public static final int GL_MAX_RENDERBUFFER_SIZE_OES                            = 0x84E8;
+    public static final int GL_INVALID_FRAMEBUFFER_OPERATION_OES                    = 0x0506;
+    public static final int GL_WRITE_ONLY_OES                                       = 0x88B9;
+    public static final int GL_BUFFER_ACCESS_OES                                    = 0x88BB;
+    public static final int GL_BUFFER_MAPPED_OES                                    = 0x88BC;
+    public static final int GL_BUFFER_MAP_POINTER_OES                               = 0x88BD;
+    public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES               = 0x898D;
+    public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES              = 0x898E;
+    public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES                 = 0x898F;
+    public static final int GL_MAX_VERTEX_UNITS_OES                                 = 0x86A4;
+    public static final int GL_MAX_PALETTE_MATRICES_OES                             = 0x8842;
+    public static final int GL_MATRIX_PALETTE_OES                                   = 0x8840;
+    public static final int GL_MATRIX_INDEX_ARRAY_OES                               = 0x8844;
+    public static final int GL_WEIGHT_ARRAY_OES                                     = 0x86AD;
+    public static final int GL_CURRENT_PALETTE_MATRIX_OES                           = 0x8843;
+    public static final int GL_MATRIX_INDEX_ARRAY_SIZE_OES                          = 0x8846;
+    public static final int GL_MATRIX_INDEX_ARRAY_TYPE_OES                          = 0x8847;
+    public static final int GL_MATRIX_INDEX_ARRAY_STRIDE_OES                        = 0x8848;
+    public static final int GL_MATRIX_INDEX_ARRAY_POINTER_OES                       = 0x8849;
+    public static final int GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES                = 0x8B9E;
+    public static final int GL_WEIGHT_ARRAY_SIZE_OES                                = 0x86AB;
+    public static final int GL_WEIGHT_ARRAY_TYPE_OES                                = 0x86A9;
+    public static final int GL_WEIGHT_ARRAY_STRIDE_OES                              = 0x86AA;
+    public static final int GL_WEIGHT_ARRAY_POINTER_OES                             = 0x86AC;
+    public static final int GL_WEIGHT_ARRAY_BUFFER_BINDING_OES                      = 0x889E;
+    public static final int GL_DEPTH_STENCIL_OES                                    = 0x84F9;
+    public static final int GL_UNSIGNED_INT_24_8_OES                                = 0x84FA;
+    public static final int GL_DEPTH24_STENCIL8_OES                                 = 0x88F0;
+    public static final int GL_RGB8_OES                                             = 0x8051;
+    public static final int GL_RGBA8_OES                                            = 0x8058;
+    public static final int GL_STENCIL_INDEX1_OES                                   = 0x8D46;
+    public static final int GL_STENCIL_INDEX4_OES                                   = 0x8D47;
+    public static final int GL_STENCIL_INDEX8_OES                                   = 0x8D48;
+    public static final int GL_INCR_WRAP_OES                                        = 0x8507;
+    public static final int GL_DECR_WRAP_OES                                        = 0x8508;
+    public static final int GL_NORMAL_MAP_OES                                       = 0x8511;
+    public static final int GL_REFLECTION_MAP_OES                                   = 0x8512;
+    public static final int GL_TEXTURE_CUBE_MAP_OES                                 = 0x8513;
+    public static final int GL_TEXTURE_BINDING_CUBE_MAP_OES                         = 0x8514;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES                      = 0x8515;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES                      = 0x8516;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES                      = 0x8517;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES                      = 0x8518;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES                      = 0x8519;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES                      = 0x851A;
+    public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES                        = 0x851C;
+    public static final int GL_TEXTURE_GEN_MODE_OES                                 = 0x2500;
+    public static final int GL_TEXTURE_GEN_STR_OES                                  = 0x8D60;
+    public static final int GL_MIRRORED_REPEAT_OES                                  = 0x8370;
+    public static final int GL_3DC_X_AMD                                            = 0x87F9;
+    public static final int GL_3DC_XY_AMD                                           = 0x87FA;
+    public static final int GL_ATC_RGB_AMD                                          = 0x8C92;
+    public static final int GL_ATC_RGBA_EXPLICIT_ALPHA_AMD                          = 0x8C93;
+    public static final int GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD                      = 0x87EE;
+    public static final int GL_TEXTURE_MAX_ANISOTROPY_EXT                           = 0x84FE;
+    public static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       = 0x84FF;
+    public static final int GL_BGRA                                                 = 0x80E1;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+    
\ No newline at end of file
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
similarity index 97%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index 6495686..3e5c19c 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -44,7 +44,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11Header.java-if b/opengl/tools/glgen/stubs/gles11/GLES11Header.java-if
new file mode 100644
index 0000000..26f466f
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES11Header.java-if
@@ -0,0 +1,151 @@
+**
+** 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.
+*/
+
+// This source file is automatically generated
+
+package android.opengl;
+
+import java.nio.Buffer;
+
+public class GLES11 extends GLES10 {
+    public static final int GL_ACTIVE_TEXTURE                          = 0x84E0;
+    public static final int GL_ADD_SIGNED                              = 0x8574;
+    public static final int GL_ALPHA_SCALE                             = 0x0D1C;
+    public static final int GL_ALPHA_TEST_FUNC                         = 0x0BC1;
+    public static final int GL_ALPHA_TEST_REF                          = 0x0BC2;
+    public static final int GL_ARRAY_BUFFER                            = 0x8892;
+    public static final int GL_ARRAY_BUFFER_BINDING                    = 0x8894;
+    public static final int GL_BLEND_DST                               = 0x0BE0;
+    public static final int GL_BLEND_SRC                               = 0x0BE1;
+    public static final int GL_BUFFER_ACCESS                           = 0x88BB;
+    public static final int GL_BUFFER_SIZE                             = 0x8764;
+    public static final int GL_BUFFER_USAGE                            = 0x8765;
+    public static final int GL_CLIENT_ACTIVE_TEXTURE                   = 0x84E1;
+    public static final int GL_CLIP_PLANE0                             = 0x3000;
+    public static final int GL_CLIP_PLANE1                             = 0x3001;
+    public static final int GL_CLIP_PLANE2                             = 0x3002;
+    public static final int GL_CLIP_PLANE3                             = 0x3003;
+    public static final int GL_CLIP_PLANE4                             = 0x3004;
+    public static final int GL_CLIP_PLANE5                             = 0x3005;
+    public static final int GL_COLOR_ARRAY_BUFFER_BINDING              = 0x8898;
+    public static final int GL_COLOR_ARRAY_POINTER                     = 0x8090;
+    public static final int GL_COLOR_ARRAY_SIZE                        = 0x8081;
+    public static final int GL_COLOR_ARRAY_STRIDE                      = 0x8083;
+    public static final int GL_COLOR_ARRAY_TYPE                        = 0x8082;
+    public static final int GL_COLOR_CLEAR_VALUE                       = 0x0C22;
+    public static final int GL_COLOR_WRITEMASK                         = 0x0C23;
+    public static final int GL_COMBINE                                 = 0x8570;
+    public static final int GL_COMBINE_ALPHA                           = 0x8572;
+    public static final int GL_COMBINE_RGB                             = 0x8571;
+    public static final int GL_CONSTANT                                = 0x8576;
+    public static final int GL_COORD_REPLACE_OES                       = 0x8862;
+    public static final int GL_CULL_FACE_MODE                          = 0x0B45;
+    public static final int GL_CURRENT_COLOR                           = 0x0B00;
+    public static final int GL_CURRENT_NORMAL                          = 0x0B02;
+    public static final int GL_CURRENT_TEXTURE_COORDS                  = 0x0B03;
+    public static final int GL_DEPTH_CLEAR_VALUE                       = 0x0B73;
+    public static final int GL_DEPTH_FUNC                              = 0x0B74;
+    public static final int GL_DEPTH_RANGE                             = 0x0B70;
+    public static final int GL_DEPTH_WRITEMASK                         = 0x0B72;
+    public static final int GL_DOT3_RGB                                = 0x86AE;
+    public static final int GL_DOT3_RGBA                               = 0x86AF;
+    public static final int GL_DYNAMIC_DRAW                            = 0x88E8;
+    public static final int GL_ELEMENT_ARRAY_BUFFER                    = 0x8893;
+    public static final int GL_ELEMENT_ARRAY_BUFFER_BINDING            = 0x8895;
+    public static final int GL_FRONT_FACE                              = 0x0B46;
+    public static final int GL_GENERATE_MIPMAP                         = 0x8191;
+    public static final int GL_GENERATE_MIPMAP_HINT                    = 0x8192;
+    public static final int GL_INTERPOLATE                             = 0x8575;
+    public static final int GL_LINE_WIDTH                              = 0x0B21;
+    public static final int GL_LOGIC_OP_MODE                           = 0x0BF0;
+    public static final int GL_MATRIX_MODE                             = 0x0BA0;
+    public static final int GL_MAX_CLIP_PLANES                         = 0x0D32;
+    public static final int GL_MODELVIEW_MATRIX                        = 0x0BA6;
+    public static final int GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES  = 0x898D;
+    public static final int GL_MODELVIEW_STACK_DEPTH                   = 0x0BA3;
+    public static final int GL_NORMAL_ARRAY_BUFFER_BINDING             = 0x8897;
+    public static final int GL_NORMAL_ARRAY_POINTER                    = 0x808F;
+    public static final int GL_NORMAL_ARRAY_STRIDE                     = 0x807F;
+    public static final int GL_NORMAL_ARRAY_TYPE                       = 0x807E;
+    public static final int GL_OPERAND0_ALPHA                          = 0x8598;
+    public static final int GL_OPERAND0_RGB                            = 0x8590;
+    public static final int GL_OPERAND1_ALPHA                          = 0x8599;
+    public static final int GL_OPERAND1_RGB                            = 0x8591;
+    public static final int GL_OPERAND2_ALPHA                          = 0x859A;
+    public static final int GL_OPERAND2_RGB                            = 0x8592;
+    public static final int GL_POINT_DISTANCE_ATTENUATION              = 0x8129;
+    public static final int GL_POINT_FADE_THRESHOLD_SIZE               = 0x8128;
+    public static final int GL_POINT_SIZE                              = 0x0B11;
+    public static final int GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES     = 0x8B9F;
+    public static final int GL_POINT_SIZE_ARRAY_OES                    = 0x8B9C;
+    public static final int GL_POINT_SIZE_ARRAY_POINTER_OES            = 0x898C;
+    public static final int GL_POINT_SIZE_ARRAY_STRIDE_OES             = 0x898B;
+    public static final int GL_POINT_SIZE_ARRAY_TYPE_OES               = 0x898A;
+    public static final int GL_POINT_SIZE_MAX                          = 0x8127;
+    public static final int GL_POINT_SIZE_MIN                          = 0x8126;
+    public static final int GL_POINT_SPRITE_OES                        = 0x8861;
+    public static final int GL_POLYGON_OFFSET_FACTOR                   = 0x8038;
+    public static final int GL_POLYGON_OFFSET_UNITS                    = 0x2A00;
+    public static final int GL_PREVIOUS                                = 0x8578;
+    public static final int GL_PRIMARY_COLOR                           = 0x8577;
+    public static final int GL_PROJECTION_MATRIX                       = 0x0BA7;
+    public static final int GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES = 0x898E;
+    public static final int GL_PROJECTION_STACK_DEPTH                  = 0x0BA4;
+    public static final int GL_RGB_SCALE                               = 0x8573;
+    public static final int GL_SAMPLE_BUFFERS                          = 0x80A8;
+    public static final int GL_SAMPLE_COVERAGE_INVERT                  = 0x80AB;
+    public static final int GL_SAMPLE_COVERAGE_VALUE                   = 0x80AA;
+    public static final int GL_SAMPLES                                 = 0x80A9;
+    public static final int GL_SCISSOR_BOX                             = 0x0C10;
+    public static final int GL_SHADE_MODEL                             = 0x0B54;
+    public static final int GL_SRC0_ALPHA                              = 0x8588;
+    public static final int GL_SRC0_RGB                                = 0x8580;
+    public static final int GL_SRC1_ALPHA                              = 0x8589;
+    public static final int GL_SRC1_RGB                                = 0x8581;
+    public static final int GL_SRC2_ALPHA                              = 0x858A;
+    public static final int GL_SRC2_RGB                                = 0x8582;
+    public static final int GL_STATIC_DRAW                             = 0x88E4;
+    public static final int GL_STENCIL_CLEAR_VALUE                     = 0x0B91;
+    public static final int GL_STENCIL_FAIL                            = 0x0B94;
+    public static final int GL_STENCIL_FUNC                            = 0x0B92;
+    public static final int GL_STENCIL_PASS_DEPTH_FAIL                 = 0x0B95;
+    public static final int GL_STENCIL_PASS_DEPTH_PASS                 = 0x0B96;
+    public static final int GL_STENCIL_REF                             = 0x0B97;
+    public static final int GL_STENCIL_VALUE_MASK                      = 0x0B93;
+    public static final int GL_STENCIL_WRITEMASK                       = 0x0B98;
+    public static final int GL_SUBTRACT                                = 0x84E7;
+    public static final int GL_TEXTURE_BINDING_2D                      = 0x8069;
+    public static final int GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING      = 0x889A;
+    public static final int GL_TEXTURE_COORD_ARRAY_POINTER             = 0x8092;
+    public static final int GL_TEXTURE_COORD_ARRAY_SIZE                = 0x8088;
+    public static final int GL_TEXTURE_COORD_ARRAY_STRIDE              = 0x808A;
+    public static final int GL_TEXTURE_COORD_ARRAY_TYPE                = 0x8089;
+    public static final int GL_TEXTURE_MATRIX                          = 0x0BA8;
+    public static final int GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES    = 0x898F;
+    public static final int GL_TEXTURE_STACK_DEPTH                     = 0x0BA5;
+    public static final int GL_VERTEX_ARRAY_BUFFER_BINDING             = 0x8896;
+    public static final int GL_VERTEX_ARRAY_POINTER                    = 0x808E;
+    public static final int GL_VERTEX_ARRAY_SIZE                       = 0x807A;
+    public static final int GL_VERTEX_ARRAY_STRIDE                     = 0x807C;
+    public static final int GL_VERTEX_ARRAY_TYPE                       = 0x807B;
+    public static final int GL_VIEWPORT                                = 0x0BA2;
+    public static final int GL_WRITE_ONLY                              = 0x88B9;
+
+    native private static void _nativeClassInit();
+    static {
+	    _nativeClassInit();
+    }
+
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
similarity index 98%
copy from opengl/tools/glgen/stubs/GLCHeader.cpp
copy to opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index 6495686..3e5c19c 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -1,5 +1,5 @@
 **
-** Copyright 2006, The Android Open Source Project
+** 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. 
@@ -44,7 +44,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/glGetString.cpp b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
similarity index 97%
rename from opengl/tools/glgen/stubs/glGetString.cpp
rename to opengl/tools/glgen/stubs/gles11/glGetString.cpp
index 22e1297..a400859 100644
--- a/opengl/tools/glgen/stubs/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
@@ -1,6 +1,7 @@
 #include <string.h>

 

 /* const GLubyte * glGetString ( GLenum name ) */

+static

 jstring

 android_glGetString

   (JNIEnv *_env, jobject _this, jint name) {

diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.java b/opengl/tools/glgen/stubs/gles11/glGetString.java
new file mode 100644
index 0000000..fba249b
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.java
@@ -0,0 +1,5 @@
+    // C function const GLubyte * glGetString ( GLenum name )

+

+    public static native String glGetString(

+        int name

+    );

diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg
new file mode 100644
index 0000000..a4af31f
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.nativeReg
@@ -0,0 +1 @@
+{"glGetString", "(I)Ljava/lang/String;", (void *) android_glGetString },

diff --git a/opengl/tools/glgen/stubs/GL10ExtHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GL10ExtHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL10ExtHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL10ExtHeader.java-if
diff --git a/opengl/tools/glgen/stubs/GL10Header.java-if b/opengl/tools/glgen/stubs/jsr239/GL10Header.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL10Header.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL10Header.java-if
diff --git a/opengl/tools/glgen/stubs/GL11ExtHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GL11ExtHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11ExtHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL11ExtHeader.java-if
diff --git a/opengl/tools/glgen/stubs/GL11ExtensionPackHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GL11ExtensionPackHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11ExtensionPackHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL11ExtensionPackHeader.java-if
diff --git a/opengl/tools/glgen/stubs/GL11Header.java-if b/opengl/tools/glgen/stubs/jsr239/GL11Header.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11Header.java-if
rename to opengl/tools/glgen/stubs/jsr239/GL11Header.java-if
diff --git a/opengl/tools/glgen/stubs/GL11ImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GL11ImplHeader.java-impl
similarity index 100%
rename from opengl/tools/glgen/stubs/GL11ImplHeader.java-impl
rename to opengl/tools/glgen/stubs/jsr239/GL11ImplHeader.java-impl
diff --git a/opengl/tools/glgen/stubs/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
similarity index 99%
rename from opengl/tools/glgen/stubs/GLCHeader.cpp
rename to opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 6495686..4636081 100644
--- a/opengl/tools/glgen/stubs/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -44,7 +44,7 @@
 
 /* Cache method IDs each time the class is loaded. */
 
-void
+static void
 nativeClassInitBuffer(JNIEnv *_env)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
diff --git a/opengl/tools/glgen/stubs/GLHeader.java-if b/opengl/tools/glgen/stubs/jsr239/GLHeader.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/GLHeader.java-if
rename to opengl/tools/glgen/stubs/jsr239/GLHeader.java-if
diff --git a/opengl/tools/glgen/stubs/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
similarity index 100%
rename from opengl/tools/glgen/stubs/GLImplHeader.java-impl
rename to opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
diff --git a/opengl/tools/glgen/stubs/glGetString.cpp b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
similarity index 97%
copy from opengl/tools/glgen/stubs/glGetString.cpp
copy to opengl/tools/glgen/stubs/jsr239/glGetString.cpp
index 22e1297..a400859 100644
--- a/opengl/tools/glgen/stubs/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
@@ -1,6 +1,7 @@
 #include <string.h>

 

 /* const GLubyte * glGetString ( GLenum name ) */

+static

 jstring

 android_glGetString

   (JNIEnv *_env, jobject _this, jint name) {

diff --git a/opengl/tools/glgen/stubs/glGetString.java-10-if b/opengl/tools/glgen/stubs/jsr239/glGetString.java-10-if
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.java-10-if
rename to opengl/tools/glgen/stubs/jsr239/glGetString.java-10-if
diff --git a/opengl/tools/glgen/stubs/glGetString.java-if b/opengl/tools/glgen/stubs/jsr239/glGetString.java-if
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.java-if
rename to opengl/tools/glgen/stubs/jsr239/glGetString.java-if
diff --git a/opengl/tools/glgen/stubs/glGetString.java-impl b/opengl/tools/glgen/stubs/jsr239/glGetString.java-impl
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.java-impl
rename to opengl/tools/glgen/stubs/jsr239/glGetString.java-impl
diff --git a/opengl/tools/glgen/stubs/glGetString.nativeReg b/opengl/tools/glgen/stubs/jsr239/glGetString.nativeReg
similarity index 100%
rename from opengl/tools/glgen/stubs/glGetString.nativeReg
rename to opengl/tools/glgen/stubs/jsr239/glGetString.nativeReg
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index d39934b..b9d567c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -38,6 +38,7 @@
 import android.util.Log;
 import android.util.Xml;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.telephony.RILConstants;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
@@ -175,7 +176,8 @@
                 // Shortcuts, applications, folders
                 db.execSQL("UPDATE favorites SET spanX=1, spanY=1 WHERE itemType<=0");
                 // Photo frames, clocks
-                db.execSQL("UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
+                db.execSQL(
+                    "UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
                 // Search boxes
                 db.execSQL("UPDATE favorites SET spanX=4, spanY=1 WHERE itemType=1001");
                 db.setTransactionSuccessful();
@@ -582,6 +584,8 @@
                 + " VALUES(?,?);");
         
         Resources r = mContext.getResources();
+        loadSetting(stmt, Settings.Secure.CURRENT_ACTIVE_PHONE,
+                RILConstants.CDMA_PHONE);
         loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
                 R.bool.def_dim_screen);
         loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN, 
@@ -655,6 +659,18 @@
             loadSetting(stmt, Settings.Secure.WIFI_WATCHDOG_WATCH_LIST, wifiWatchList);
         }
 
+        // Set the preferred network mode to 0 = Global, CDMA default
+        loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, 
+                RILConstants.PREFERRED_NETWORK_MODE);
+
+        // Enable or disable Cell Broadcast SMS
+        loadSetting(stmt, Settings.Secure.CDMA_CELL_BROADCAST_SMS,
+                RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
+
+        // Set the preferred cdma subscription to 0 = Subscription from RUIM, when available
+        loadSetting(stmt, Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, 
+                RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
+
         // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
         // persistent system property instead.
         //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
@@ -691,3 +707,4 @@
                 Float.toString(mContext.getResources().getFraction(resid, base, base)));
     }
 }
+
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 333a450..6f430c4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -244,6 +244,72 @@
         return values.length;
     }
 
+    /*
+     * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
+     * This setting contains a list of the currently enabled location providers.
+     * But helper functions in android.providers.Settings can enable or disable
+     * a single provider by using a "+" or "-" prefix before the provider name.
+     */
+    private boolean parseProviderList(Uri url, ContentValues initialValues) {
+        String value = initialValues.getAsString(Settings.Secure.VALUE);
+        String newProviders = null;
+        if (value != null && value.length() > 1) {
+            char prefix = value.charAt(0);
+            if (prefix == '+' || prefix == '-') {
+                // skip prefix
+                value = value.substring(1);
+
+                // read list of enabled providers into "providers"
+                String providers = "";
+                String[] columns = {Settings.Secure.VALUE};
+                String where = Settings.Secure.NAME + "=\'" + Settings.Secure.LOCATION_PROVIDERS_ALLOWED + "\'";
+                Cursor cursor = query(url, columns, where, null, null);
+                if (cursor != null && cursor.getCount() == 1) {
+                    try {
+                        cursor.moveToFirst();
+                        providers = cursor.getString(0);
+                    } finally {
+                        cursor.close();
+                    }
+                }
+
+                int index = providers.indexOf(value);
+                int end = index + value.length();
+                // check for commas to avoid matching on partial string
+                if (index > 0 && providers.charAt(index - 1) != ',') index = -1;
+                if (end < providers.length() && providers.charAt(end) != ',') index = -1;
+
+                if (prefix == '+' && index < 0) {
+                    // append the provider to the list if not present
+                    if (providers.length() == 0) {
+                        newProviders = value;
+                    } else {
+                        newProviders = providers + ',' + value;
+                    }
+                } else if (prefix == '-' && index >= 0) {
+                    // remove the provider from the list if present
+                    // remove leading and trailing commas
+                    if (index > 0) index--;
+                    if (end < providers.length()) end++;
+
+                    newProviders = providers.substring(0, index);
+                    if (end < providers.length()) {
+                        newProviders += providers.substring(end);
+                    }
+                } else {
+                    // nothing changed, so no need to update the database
+                    return false;
+                }
+
+                if (newProviders != null) {
+                    initialValues.put(Settings.Secure.VALUE, newProviders);
+                }
+            }
+        }
+        
+        return true;
+    }
+
     @Override
     public Uri insert(Uri url, ContentValues initialValues) {
         SqlArguments args = new SqlArguments(url);
@@ -252,6 +318,13 @@
         }
         checkWritePermissions(args);
 
+        // Special case LOCATION_PROVIDERS_ALLOWED.
+        // Support enabling/disabling a single provider (using "+" or "-" prefix)
+        String name = initialValues.getAsString(Settings.Secure.NAME);
+        if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
+            if (!parseProviderList(url, initialValues)) return null;
+        }
+
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         final long rowId = db.insert(args.table, null, initialValues);
         if (rowId <= 0) return null;
diff --git a/preloaded-classes b/preloaded-classes
index e3197b41..7d719e9 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -300,8 +300,8 @@
 android.telephony.PhoneStateListener
 android.telephony.ServiceState
 android.telephony.TelephonyManager
-android.telephony.gsm.SmsManager
-android.telephony.gsm.SmsMessage
+android.telephony.SmsManager
+android.telephony.SmsMessage
 android.text.AutoText
 android.text.BoringLayout
 android.text.BoringLayout$Metrics
@@ -453,17 +453,22 @@
 android.view.inputmethod.BaseInputConnection
 android.view.inputmethod.CompletionInfo
 android.view.inputmethod.CompletionInfo$1
+
 android.view.inputmethod.EditorInfo
 android.view.inputmethod.EditorInfo$1
+
 android.view.inputmethod.ExtractedText
 android.view.inputmethod.ExtractedText$1
+
 android.view.inputmethod.ExtractedTextRequest
 android.view.inputmethod.ExtractedTextRequest$1
+
 android.view.inputmethod.InputBinding
 android.view.inputmethod.InputBinding$1
 android.view.inputmethod.InputConnection
 android.view.inputmethod.InputMethod
 android.view.inputmethod.InputMethod$SessionCallback
+
 android.view.inputmethod.InputMethodInfo
 android.view.inputmethod.InputMethodInfo$1
 android.view.inputmethod.InputMethodManager
@@ -471,6 +476,7 @@
 android.view.inputmethod.InputMethodManager$2
 android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper
 android.view.inputmethod.InputMethodManager$H
+
 android.view.inputmethod.InputMethodSession
 android.view.inputmethod.InputMethodSession$EventCallback
 android.webkit.BrowserFrame
@@ -629,50 +635,59 @@
 com.android.internal.telephony.Phone$SuppService
 com.android.internal.telephony.PhoneBase
 com.android.internal.telephony.PhoneStateIntentReceiver
-com.android.internal.telephony.SimCard$State
-com.android.internal.telephony.gsm.BaseCommands
-com.android.internal.telephony.gsm.CallForwardInfo
-com.android.internal.telephony.gsm.CommandsInterface
-com.android.internal.telephony.gsm.DriverCall
-com.android.internal.telephony.gsm.DriverCall$State
-com.android.internal.telephony.gsm.GSMConnection
+com.android.internal.telephony.IccCard$State
+com.android.internal.telephony.BaseCommands
+com.android.internal.telephony.CallForwardInfo
+com.android.internal.telephony.CommandsInterface
+com.android.internal.telephony.DriverCall
+com.android.internal.telephony.DriverCall$State
+com.android.internal.telephony.gsm.GsmConnection
 com.android.internal.telephony.gsm.GSMPhone
-com.android.internal.telephony.gsm.GsmAlphabet
+com.android.internal.telephony.GsmAlphabet
 com.android.internal.telephony.gsm.GsmMmiCode
-com.android.internal.telephony.gsm.GsmSimCard
-com.android.internal.telephony.gsm.ISms$Stub
-com.android.internal.telephony.gsm.PdpConnection$PdpFailCause
-com.android.internal.telephony.gsm.RIL
-com.android.internal.telephony.gsm.ServiceStateTracker
+com.android.internal.telephony.gsm.SimCard
+com.android.internal.telephony.ISms$Stub
+com.android.internal.telephony.RIL
+com.android.internal.telephony.ServiceStateTracker
+
 com.android.internal.telephony.gsm.stk.ComprehensionTlvTag
 com.android.internal.telephony.gsm.stk.ResultCode
 com.android.internal.util.FastXmlSerializer
 com.android.internal.view.IInputConnectionWrapper
 com.android.internal.view.IInputConnectionWrapper$MyHandler
 com.android.internal.view.IInputConnectionWrapper$SomeArgs
+
 com.android.internal.view.IInputContext
 com.android.internal.view.IInputContext$Stub
 com.android.internal.view.IInputContext$Stub$Proxy
+
 com.android.internal.view.IInputContextCallback
 com.android.internal.view.IInputContextCallback$Stub
 com.android.internal.view.IInputContextCallback$Stub$Proxy
+
 com.android.internal.view.IInputMethod
 com.android.internal.view.IInputMethod$Stub
 com.android.internal.view.IInputMethod$Stub$Proxy
+
 com.android.internal.view.IInputMethodCallback
 com.android.internal.view.IInputMethodCallback$Stub
 com.android.internal.view.IInputMethodCallback$Stub$Proxy
+
 com.android.internal.view.IInputMethodClient
 com.android.internal.view.IInputMethodClient$Stub
 com.android.internal.view.IInputMethodClient$Stub$Proxy
+
 com.android.internal.view.IInputMethodManager
 com.android.internal.view.IInputMethodManager$Stub
 com.android.internal.view.IInputMethodManager$Stub$Proxy
+
 com.android.internal.view.IInputMethodSession
 com.android.internal.view.IInputMethodSession$Stub
 com.android.internal.view.IInputMethodSession$Stub$Proxy
+
 com.android.internal.view.InputBindResult
 com.android.internal.view.InputBindResult$1
+
 com.android.internal.view.InputConnectionWrapper
 com.android.internal.view.InputConnectionWrapper$InputContextCallback
 com.android.internal.view.menu.ExpandedMenuView
@@ -1165,3 +1180,4 @@
 org.xmlpull.v1.XmlPullParserFactory
 org.xmlpull.v1.sax2.Driver
 sun.misc.Unsafe
+
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index d66c6e5..9c4ace1 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -413,41 +413,45 @@
         
         synchronized (mLock) {
             pw.println("Current Alarm Manager state:");
-            if (mRtcWakeupAlarms.size() > 0) {
+            if (mRtcWakeupAlarms.size() > 0 || mRtcAlarms.size() > 0) {
                 pw.println(" ");
-                pw.println("  Realtime wakeup alarms that are scheduled:");
-                dumpAlarmList(pw, mRtcWakeupAlarms, "  ", "RTC_WAKEUP");
+                pw.print("  Realtime wakeup (now=");
+                        pw.print(System.currentTimeMillis()); pw.println("):");
+                if (mRtcWakeupAlarms.size() > 0) {
+                    dumpAlarmList(pw, mRtcWakeupAlarms, "  ", "RTC_WAKEUP");
+                }
+                if (mRtcAlarms.size() > 0) {
+                    dumpAlarmList(pw, mRtcAlarms, "  ", "RTC");
+                }
             }
-            if (mRtcAlarms.size() > 0) {
+            if (mElapsedRealtimeWakeupAlarms.size() > 0 || mElapsedRealtimeAlarms.size() > 0) {
                 pw.println(" ");
-                pw.println("  Realtime alarms that are scheduled:");
-                dumpAlarmList(pw, mRtcAlarms, "  ", "RTC");
-            }
-            if (mElapsedRealtimeWakeupAlarms.size() > 0) {
-                pw.println(" ");
-                pw.println("  Elapsed realtime wakeup alarms that are scheduled:");
-                dumpAlarmList(pw, mElapsedRealtimeWakeupAlarms, "  ", "ELAPSED_REALTIME_WAKEUP");
-            }
-            if (mElapsedRealtimeAlarms.size() > 0) {
-                pw.println(" ");
-                pw.println("  Elapsed realtime alarms that are scheduled:");
-                dumpAlarmList(pw, mElapsedRealtimeAlarms, "  ", "ELAPSED_REALTIME");
+                pw.print("  Elapsed realtime wakeup (now=");
+                        pw.print(SystemClock.elapsedRealtime()); pw.println("):");
+                if (mElapsedRealtimeWakeupAlarms.size() > 0) {
+                    dumpAlarmList(pw, mElapsedRealtimeWakeupAlarms, "  ", "ELAPSED_WAKEUP");
+                }
+                if (mElapsedRealtimeAlarms.size() > 0) {
+                    dumpAlarmList(pw, mElapsedRealtimeAlarms, "  ", "ELAPSED");
+                }
             }
             
             pw.println(" ");
-            pw.println("  Broadcast ref count: " + mBroadcastRefCount);
+            pw.print("  Broadcast ref count: "); pw.println(mBroadcastRefCount);
             
             pw.println(" ");
             pw.println("  Alarm Stats:");
             for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) {
                 BroadcastStats bs = be.getValue();
-                pw.println("  " + be.getKey());
-                pw.println("    " + bs.aggregateTime + "ms running, "
-                        + bs.numWakeup + " wakeups");
+                pw.print("  "); pw.println(be.getKey());
+                pw.print("    "); pw.print(bs.aggregateTime);
+                        pw.print("ms running, "); pw.print(bs.numWakeup);
+                        pw.println(" wakeups");
                 for (Map.Entry<Intent.FilterComparison, FilterStats> fe
                         : bs.filterStats.entrySet()) {
-                    pw.println("    " + fe.getValue().count + " alarms: "
-                            + fe.getKey().getIntent());
+                    pw.print("    "); pw.print(fe.getValue().count);
+                            pw.print(" alarms: ");
+                            pw.println(fe.getKey().getIntent().toShortString(true, false));
                 }
             }
         }
@@ -456,7 +460,8 @@
     private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list, String prefix, String label) {
         for (int i=list.size()-1; i>=0; i--) {
             Alarm a = list.get(i);
-            pw.println(prefix + label + " #" + i + ":");
+            pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
+                    pw.print(": "); pw.println(a);
             a.dump(pw, prefix + "  ");
         }
     }
@@ -561,18 +566,24 @@
         @Override
         public String toString()
         {
-            return "Alarm{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " type " + type + " " + operation.getTargetPackage() + "}";
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("Alarm{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(" type ");
+            sb.append(type);
+            sb.append(" ");
+            sb.append(operation.getTargetPackage());
+            sb.append('}');
+            return sb.toString();
         }
 
         public void dump(PrintWriter pw, String prefix)
         {
-            pw.println(prefix + this);
-            pw.println(prefix + "type=" + type + " when=" + when
-                  + " repeatInterval=" + repeatInterval
-                  + " count=" + count);
-            pw.println(prefix + "operation=" + operation);
+            pw.print(prefix); pw.print("type="); pw.print(type);
+                    pw.print(" when="); pw.print(when);
+                    pw.print(" repeatInterval="); pw.print(repeatInterval);
+                    pw.print(" count="); pw.println(count);
+            pw.print(prefix); pw.print("operation="); pw.println(operation);
         }
     }
     
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index de5d0ac..bb420a6e 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -151,34 +151,57 @@
 
         synchronized (mAppWidgetIds) {
             int N = mInstalledProviders.size();
-            pw.println("Providers: (size=" + N + ")");
+            pw.println("Providers:");
             for (int i=0; i<N; i++) {
                 Provider p = mInstalledProviders.get(i);
                 AppWidgetProviderInfo info = p.info;
-                pw.println("  [" + i + "] provder=" + info.provider
-                        + " min=(" + info.minWidth + "x" + info.minHeight + ")"
-                        + " updatePeriodMillis=" + info.updatePeriodMillis
-                        + " initialLayout=" + info.initialLayout + " zombie=" + p.zombie);
+                pw.print("  ["); pw.print(i); pw.print("] provider ");
+                        pw.print(info.provider.flattenToShortString());
+                        pw.println(':');
+                pw.print("    min=("); pw.print(info.minWidth);
+                        pw.print("x"); pw.print(info.minHeight);
+                        pw.print(") updatePeriodMillis=");
+                        pw.print(info.updatePeriodMillis);
+                        pw.print(" initialLayout=#");
+                        pw.print(Integer.toHexString(info.initialLayout));
+                        pw.print(" zombie="); pw.println(p.zombie);
             }
 
             N = mAppWidgetIds.size();
-            pw.println("AppWidgetIds: (size=" + N + ")");
+            pw.println(" ");
+            pw.println("AppWidgetIds:");
             for (int i=0; i<N; i++) {
                 AppWidgetId id = mAppWidgetIds.get(i);
-                pw.println("  [" + i + "] appWidgetId=" + id.appWidgetId
-                        + " host=" + id.host.hostId + "/" + id.host.packageName + " provider="
-                        + (id.provider == null ? "null" : id.provider.info.provider)
-                        + " host.callbacks=" + (id.host != null ? id.host.callbacks : "(no host)")
-                        + " views=" + id.views);
+                pw.print("  ["); pw.print(i); pw.print("] id=");
+                        pw.println(id.appWidgetId);;
+                pw.print("    hostId=");
+                        pw.print(id.host.hostId); pw.print(' ');
+                        pw.print(id.host.packageName); pw.print('/');
+                        pw.println(id.host.uid);
+                if (id.provider != null) {
+                    pw.print("    provider=");
+                            pw.println(id.provider.info.provider.flattenToShortString());
+                }
+                if (id.host != null) {
+                    pw.print("    host.callbacks="); pw.println(id.host.callbacks);
+                }
+                if (id.views != null) {
+                    pw.print("    views="); pw.println(id.views);
+                }
             }
 
             N = mHosts.size();
-            pw.println("Hosts: (size=" + N + ")");
+            pw.println(" ");
+            pw.println("Hosts:");
             for (int i=0; i<N; i++) {
                 Host host = mHosts.get(i);
-                pw.println("  [" + i + "] packageName=" + host.packageName + " uid=" + host.uid
-                        + " hostId=" + host.hostId + " callbacks=" + host.callbacks
-                        + " instances.size=" + host.instances.size() + " zombie=" + host.zombie);
+                pw.print("  ["); pw.print(i); pw.print("] hostId=");
+                        pw.print(host.hostId); pw.print(' ');
+                        pw.print(host.packageName); pw.print('/');
+                        pw.print(host.uid); pw.println(':');
+                pw.print("    callbacks="); pw.println(host.callbacks);
+                pw.print("    instances.size="); pw.print(host.instances.size());
+                        pw.print(" zombie="); pw.println(host.zombie);
             }
         }
     }
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 73ff501..90d8c9d 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -84,7 +84,7 @@
     private static final int CRITICAL_BATTERY_LEVEL = 4; 
 
     private static final int DUMP_MAX_LENGTH = 24 * 1024;
-    private static final String[] DUMPSYS_ARGS = new String[] { "-c", "-u" };
+    private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "-u" };
     private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo";
     
     private static final String DUMPSYS_DATA_PATH = "/data/system/";
@@ -229,6 +229,16 @@
                 EventLog.writeEvent(LOG_BATTERY_LEVEL,
                         mBatteryLevel, mBatteryVoltage, mBatteryTemperature);
             }
+            if (mBatteryLevel != mLastBatteryLevel && mPlugType == BATTERY_PLUGGED_NONE) {
+                // If the battery level has changed and we are on battery, update the current level.
+                // This is used for discharge cycle tracking so this shouldn't be updated while the 
+                // battery is charging.
+                try {
+                    mBatteryStats.recordCurrentLevel(mBatteryLevel);
+                } catch (RemoteException e) {
+                    // Should never happen.
+                }
+            }
             if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
                     mPlugType == BATTERY_PLUGGED_NONE) {
                 // We want to make sure we log discharge cycle outliers
@@ -237,6 +247,20 @@
                 logOutlier = true;
             }
             
+            // Separate broadcast is sent for power connected / not connected
+            // since the standard intent will not wake any applications and some
+            // applications may want to have smart behavior based on this.
+            if (mPlugType != 0 && mLastPlugType == 0) {
+                Intent intent = new Intent(Intent.ACTION_POWER_CONNECTED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                mContext.sendBroadcast(intent);
+            }
+            else if (mPlugType == 0 && mLastPlugType != 0) {
+                Intent intent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                mContext.sendBroadcast(intent);
+            }
+            
             mLastBatteryStatus = mBatteryStatus;
             mLastBatteryHealth = mBatteryHealth;
             mLastBatteryPresent = mBatteryPresent;
diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java
index c9066be..3fc1e0e 100644
--- a/services/java/com/android/server/HeadsetObserver.java
+++ b/services/java/com/android/server/HeadsetObserver.java
@@ -21,6 +21,8 @@
 import android.content.Intent;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
 import android.os.UEventObserver;
 import android.util.Log;
 import android.media.AudioManager;
@@ -38,15 +40,19 @@
     private static final String HEADSET_STATE_PATH = "/sys/class/switch/h2w/state";
     private static final String HEADSET_NAME_PATH = "/sys/class/switch/h2w/name";
 
-    private Context mContext;
-
     private int mHeadsetState;
     private String mHeadsetName;
     private boolean mAudioRouteNeedsUpdate;
     private AudioManager mAudioManager;
 
+    private final Context mContext;
+    private final WakeLock mWakeLock;  // held while there is a pending route change
+
     public HeadsetObserver(Context context) {
         mContext = context;
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetObserver");
+        mWakeLock.setReferenceCounted(false);
 
         startObserving(HEADSET_UEVENT_MATCH);
 
@@ -103,6 +109,7 @@
                 // immediate, so delay the route change by 1000ms.
                 // This could be improved once the audio sub-system provides an
                 // interface to clear the audio pipeline.
+                mWakeLock.acquire();
                 mHandler.sendEmptyMessageDelayed(0, 1000);
             } else {
                 updateAudioRoute();
@@ -138,7 +145,8 @@
         @Override
         public void handleMessage(Message msg) {
             updateAudioRoute();
+            mWakeLock.release();
         }
-    };        
+    };
 
 }
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index b534ef1..72efca5 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -89,11 +90,11 @@
         }
     }
 
-    void dumpMap(Printer out, String prefix, Map<String, ArrayList<F>> map) {
+    void dumpMap(PrintWriter out, String prefix, Map<String, ArrayList<F>> map) {
         String eprefix = prefix + "  ";
         String fprefix = prefix + "    ";
         for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
-            out.println(eprefix + e.getKey() + ":");
+            out.print(eprefix); out.print(e.getKey()); out.println(":");
             ArrayList<F> a = e.getValue();
             final int N = a.size();
             for (int i=0; i<N; i++) {
@@ -102,24 +103,25 @@
         }
     }
 
-    public void dump(Printer out, String prefix) {
-        out.println(prefix + "Full MIME Types:");
-        dumpMap(out, prefix+"  ", mTypeToFilter);
-        out.println(prefix);
-        out.println(prefix + "Base MIME Types:");
-        dumpMap(out, prefix+"  ", mBaseTypeToFilter);
-        out.println(prefix);
-        out.println(prefix + "Wild MIME Types:");
-        dumpMap(out, prefix+"  ", mWildTypeToFilter);
-        out.println(prefix);
-        out.println(prefix + "Schemes:");
-        dumpMap(out, prefix+"  ", mSchemeToFilter);
-        out.println(prefix);
-        out.println(prefix + "Non-Data Actions:");
-        dumpMap(out, prefix+"  ", mActionToFilter);
-        out.println(prefix);
-        out.println(prefix + "MIME Typed Actions:");
-        dumpMap(out, prefix+"  ", mTypedActionToFilter);
+    public void dump(PrintWriter out, String prefix) {
+        String innerPrefix = prefix + "  ";
+        out.print(prefix); out.println("Full MIME Types:");
+        dumpMap(out, innerPrefix, mTypeToFilter);
+        out.println(" ");
+        out.print(prefix); out.println("Base MIME Types:");
+        dumpMap(out, innerPrefix, mBaseTypeToFilter);
+        out.println(" ");
+        out.print(prefix); out.println("Wild MIME Types:");
+        dumpMap(out, innerPrefix, mWildTypeToFilter);
+        out.println(" ");
+        out.print(prefix); out.println("Schemes:");
+        dumpMap(out, innerPrefix, mSchemeToFilter);
+        out.println(" ");
+        out.print(prefix); out.println("Non-Data Actions:");
+        dumpMap(out, innerPrefix, mActionToFilter);
+        out.println(" ");
+        out.print(prefix); out.println("MIME Typed Actions:");
+        dumpMap(out, innerPrefix, mTypedActionToFilter);
     }
 
     private class IteratorWrapper implements Iterator<F> {
@@ -275,8 +277,8 @@
         Collections.sort(results, mResolvePrioritySorter);
     }
 
-    protected void dumpFilter(Printer out, String prefix, F filter) {
-        out.println(prefix + filter);
+    protected void dumpFilter(PrintWriter out, String prefix, F filter) {
+        out.print(prefix); out.println(filter);
     }
 
     private final int register_mime_types(F filter, String prefix) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 705ddb3..0e1e0d9 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -28,53 +28,53 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Observable;
+import java.util.Observer;
 import java.util.Set;
 import java.util.regex.Pattern;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.database.Cursor;
 import android.location.Address;
+import android.location.IGeocodeProvider;
 import android.location.IGpsStatusListener;
+import android.location.ILocationCollector;
 import android.location.ILocationListener;
 import android.location.ILocationManager;
+import android.location.ILocationProvider;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
-import android.location.LocationProviderImpl;
 import android.net.ConnectivityManager;
 import android.net.Uri;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.provider.Settings;
-import android.telephony.CellLocation;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
 import android.util.Config;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.SparseIntArray;
 
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.CellState;
 import com.android.internal.location.GpsLocationProvider;
-import com.android.internal.location.ILocationCollector;
-import com.android.internal.location.INetworkLocationManager;
-import com.android.internal.location.INetworkLocationProvider;
-import com.android.internal.location.TrackProvider;
+import com.android.internal.location.LocationProviderImpl;
+import com.android.internal.location.LocationProviderProxy;
+import com.android.internal.location.MockProvider;
 import com.android.server.am.BatteryStatsService;
 
 /**
@@ -83,8 +83,7 @@
  *
  * {@hide}
  */
-public class LocationManagerService extends ILocationManager.Stub
-        implements INetworkLocationManager {
+public class LocationManagerService extends ILocationManager.Stub implements Runnable {
     private static final String TAG = "LocationManagerService";
     private static final boolean LOCAL_LOGV = false;
 
@@ -94,10 +93,6 @@
     // Max time to hold wake lock for, in milliseconds.
     private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L;
 
-    // Time to wait after releasing a wake lock for clients to process location update,
-    // in milliseconds.
-    private static final long TIME_AFTER_WAKE_LOCK = 2 * 1000L;
-
     // The last time a location was written, by provider name.
     private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
 
@@ -119,70 +114,39 @@
     private final Set<String> mDisabledProviders = new HashSet<String>();
 
     // Locations, status values, and extras for mock providers
-    HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
-    private final HashMap<String,Location> mMockProviderLocation = new HashMap<String,Location>();
-    private final HashMap<String,Integer> mMockProviderStatus = new HashMap<String,Integer>();
-    private final HashMap<String,Bundle> mMockProviderStatusExtras = new HashMap<String,Bundle>();
-    private final HashMap<String,Long> mMockProviderStatusUpdateTime = new HashMap<String,Long>();
+    private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
 
     private static boolean sProvidersLoaded = false;
 
     private final Context mContext;
     private GpsLocationProvider mGpsLocationProvider;
-    private boolean mGpsNavigating;
-    private LocationProviderImpl mNetworkLocationProvider;
-    private INetworkLocationProvider mNetworkLocationInterface;
+    private LocationProviderProxy mNetworkLocationProvider;
+    private IGeocodeProvider mGeocodeProvider;
     private LocationWorkerHandler mLocationHandler;
 
     // Handler messages
-    private static final int MESSAGE_HEARTBEAT = 1;
-    private static final int MESSAGE_ACQUIRE_WAKE_LOCK = 2;
-    private static final int MESSAGE_RELEASE_WAKE_LOCK = 3;
-    private static final int MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER = 4;
+    private static final int MESSAGE_LOCATION_CHANGED = 1;
 
     // Alarm manager and wakelock variables
     private final static String ALARM_INTENT = "com.android.location.ALARM_INTENT";
     private final static String WAKELOCK_KEY = "LocationManagerService";
-    private final static String WIFILOCK_KEY = "LocationManagerService";
     private AlarmManager mAlarmManager;
     private long mAlarmInterval = 0;
-    private boolean mScreenOn = true;
     private PowerManager.WakeLock mWakeLock = null;
-    private WifiManager.WifiLock mWifiLock = null;
+    private int mPendingBroadcasts;
     private long mWakeLockAcquireTime = 0;
     private boolean mWakeLockGpsReceived = true;
     private boolean mWakeLockNetworkReceived = true;
-    private boolean mWifiWakeLockAcquired = false;
-    private boolean mCellWakeLockAcquired = false;
-    
-    private final IBatteryStats mBatteryStats;
     
     /**
-     * Mapping from listener IBinder/PendingIntent to local Listener wrappers.
+     * List of all receivers.
      */
-    private final ArrayList<Receiver> mListeners = new ArrayList<Receiver>();
+    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
 
     /**
-     * Used for reporting which UIDs are causing the GPS to run.
+     * Object used internally for synchronization
      */
-    private final SparseIntArray mReportedGpsUids = new SparseIntArray();
-    private int mReportedGpsSeq = 0;
-    
-    /**
-     * Mapping from listener IBinder/PendingIntent to a map from provider name to UpdateRecord.
-     * This also serves as the lock for our state.
-     */
-    private final HashMap<Receiver,HashMap<String,UpdateRecord>> mLocationListeners =
-        new HashMap<Receiver,HashMap<String,UpdateRecord>>();
-
-    /**
-     * Mapping from listener IBinder/PendingIntent to a map from provider name to last broadcast
-     * location.
-     */
-    private final HashMap<Receiver,HashMap<String,Location>> mLastFixBroadcast =
-        new HashMap<Receiver,HashMap<String,Location>>();
-    private final HashMap<Receiver,HashMap<String,Long>> mLastStatusBroadcast =
-        new HashMap<Receiver,HashMap<String,Long>>();
+    private final Object mLock = new Object();
 
     /**
      * Mapping from provider name to all its UpdateRecords
@@ -190,15 +154,9 @@
     private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider =
         new HashMap<String,ArrayList<UpdateRecord>>();
 
-    /**
-     * Mappings from provider name to object to use for current location. Locations
-     * contained in this list may not always be valid.
-     */
-    private final HashMap<String,Location> mLocationsByProvider =
-        new HashMap<String,Location>();
-
     // Proximity listeners
-    private Receiver mProximityListener = null;
+    private Receiver mProximityReceiver = null;
+    private ILocationListener mProximityListener = null;
     private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
         new HashMap<PendingIntent,ProximityAlert>();
     private HashSet<ProximityAlert> mProximitiesEntered =
@@ -208,44 +166,34 @@
     private HashMap<String,Location> mLastKnownLocation =
         new HashMap<String,Location>();
 
-    // Battery status extras (from com.android.server.BatteryService)
-    private static final String BATTERY_EXTRA_SCALE = "scale";
-    private static final String BATTERY_EXTRA_LEVEL = "level";
-    private static final String BATTERY_EXTRA_PLUGGED = "plugged";
-
-    // Last known cell service state
-    private TelephonyManager mTelephonyManager;
-
     // Location collector
     private ILocationCollector mCollector;
 
-    // Wifi Manager
-    private WifiManager mWifiManager;
-
     private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
-    private boolean mWifiEnabled = false;
+
+    // for Settings change notification
+    private ContentQueryMap mSettings;
 
     /**
      * A wrapper class holding either an ILocationListener or a PendingIntent to receive
      * location updates.
      */
-    private final class Receiver implements IBinder.DeathRecipient {
+    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
         final ILocationListener mListener;
         final PendingIntent mPendingIntent;
-        final int mUid;
         final Object mKey;
+        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
+        int mPendingBroadcasts;
 
-        Receiver(ILocationListener listener, int uid) {
+        Receiver(ILocationListener listener) {
             mListener = listener;
             mPendingIntent = null;
-            mUid = uid;
             mKey = listener.asBinder();
         }
 
-        Receiver(PendingIntent intent, int uid) {
+        Receiver(PendingIntent intent) {
             mPendingIntent = intent;
             mListener = null;
-            mUid = uid;
             mKey = intent;
         }
 
@@ -269,11 +217,11 @@
             if (mListener != null) {
                 return "Receiver{"
                         + Integer.toHexString(System.identityHashCode(this))
-                        + " uid " + mUid + " Listener " + mKey + "}";
+                        + " Listener " + mKey + "}";
             } else {
                 return "Receiver{"
                         + Integer.toHexString(System.identityHashCode(this))
-                        + " uid " + mUid + " Intent " + mKey + "}";
+                        + " Intent " + mKey + "}";
             }
         }
 
@@ -302,7 +250,16 @@
         public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
             if (mListener != null) {
                 try {
-                    mListener.onStatusChanged(provider, status, extras);
+                    synchronized (this) {
+                        // synchronize to ensure incrementPendingBroadcastsLocked()
+                        // is called before decrementPendingBroadcasts()
+                        mListener.onStatusChanged(provider, status, extras);
+                        if (mListener != mProximityListener) {
+                            // call this after broadcasting so we do not increment
+                            // if we throw an exeption.
+                            incrementPendingBroadcastsLocked();
+                        }
+                    }
                 } catch (RemoteException e) {
                     return false;
                 }
@@ -311,7 +268,14 @@
                 statusChanged.putExtras(extras);
                 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
                 try {
-                    mPendingIntent.send(mContext, 0, statusChanged, null, null);
+                    synchronized (this) {
+                        // synchronize to ensure incrementPendingBroadcastsLocked()
+                        // is called before decrementPendingBroadcasts()
+                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
+                    }
                 } catch (PendingIntent.CanceledException e) {
                     return false;
                 }
@@ -322,7 +286,16 @@
         public boolean callLocationChangedLocked(Location location) {
             if (mListener != null) {
                 try {
-                    mListener.onLocationChanged(location);
+                    synchronized (this) {
+                        // synchronize to ensure incrementPendingBroadcastsLocked()
+                        // is called before decrementPendingBroadcasts()
+                        mListener.onLocationChanged(location);
+                        if (mListener != mProximityListener) {
+                            // call this after broadcasting so we do not increment
+                            // if we throw an exeption.
+                            incrementPendingBroadcastsLocked();
+                        }
+                    }
                 } catch (RemoteException e) {
                     return false;
                 }
@@ -330,7 +303,53 @@
                 Intent locationChanged = new Intent();
                 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
                 try {
-                    mPendingIntent.send(mContext, 0, locationChanged, null, null);
+                    synchronized (this) {
+                        // synchronize to ensure incrementPendingBroadcastsLocked()
+                        // is called before decrementPendingBroadcasts()
+                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
+                    }
+                } catch (PendingIntent.CanceledException e) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
+            if (mListener != null) {
+                try {
+                    synchronized (this) {
+                        // synchronize to ensure incrementPendingBroadcastsLocked()
+                        // is called before decrementPendingBroadcasts()
+                        if (enabled) {
+                            mListener.onProviderEnabled(provider);
+                        } else {
+                            mListener.onProviderDisabled(provider);
+                        }
+                        if (mListener != mProximityListener) {
+                            // call this after broadcasting so we do not increment
+                            // if we throw an exeption.
+                            incrementPendingBroadcastsLocked();
+                        }
+                    }
+                } catch (RemoteException e) {
+                    return false;
+                }
+            } else {
+                Intent providerIntent = new Intent();
+                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
+                try {
+                    synchronized (this) {
+                        // synchronize to ensure incrementPendingBroadcastsLocked()
+                        // is called before decrementPendingBroadcasts()
+                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
+                        // call this after broadcasting so we do not increment
+                        // if we throw an exeption.
+                        incrementPendingBroadcastsLocked();
+                    }
                 } catch (PendingIntent.CanceledException e) {
                     return false;
                 }
@@ -342,9 +361,53 @@
             if (LOCAL_LOGV) {
                 Log.v(TAG, "Location listener died");
             }
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 removeUpdatesLocked(this);
             }
+            synchronized (this) {
+                if (mPendingBroadcasts > 0) {
+                    LocationManagerService.this.decrementPendingBroadcasts();
+                    mPendingBroadcasts = 0;
+                }
+            }
+        }
+
+        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
+                int resultCode, String resultData, Bundle resultExtras) {
+            decrementPendingBroadcasts();
+        }
+
+        // this must be called while synchronized by callerin a synchronized block
+        // containing the sending of the broadcaset
+        private void incrementPendingBroadcastsLocked() {
+            if (mPendingBroadcasts++ == 0) {
+                synchronized (mLock) {
+                    LocationManagerService.this.incrementPendingBroadcastsLocked();
+                }
+            }
+        }
+
+        private void decrementPendingBroadcasts() {
+            synchronized (this) {
+                if (--mPendingBroadcasts == 0) {
+                    LocationManagerService.this.decrementPendingBroadcasts();
+                }
+            }
+        }
+    }
+
+    public void locationCallbackFinished(ILocationListener listener) {
+        Receiver receiver = getReceiver(listener);
+        if (receiver != null) {
+            receiver.decrementPendingBroadcasts();
+        }
+    }
+
+    private final class SettingsObserver implements Observer {
+        public void update(Observable o, Object arg) {
+            synchronized (mLock) {
+                updateProvidersLocked();
+            }
         }
     }
 
@@ -449,7 +512,7 @@
      *                                                          properties
      */
     private void loadProviders() {
-        synchronized (mLocationListeners) {
+        synchronized (mLock) {
             if (sProvidersLoaded) {
                 return;
             }
@@ -472,75 +535,10 @@
         // Attempt to load "real" providers first
         if (GpsLocationProvider.isSupported()) {
             // Create a gps location provider
-            mGpsLocationProvider = new GpsLocationProvider(mContext);
+            mGpsLocationProvider = new GpsLocationProvider(mContext, this);
             LocationProviderImpl.addProvider(mGpsLocationProvider);
         }
 
-        // Load fake providers if real providers are not available
-        File f = new File(LocationManager.PROVIDER_DIR);
-        if (f.isDirectory()) {
-            File[] subdirs = f.listFiles();
-            for (int i = 0; i < subdirs.length; i++) {
-                if (!subdirs[i].isDirectory()) {
-                    continue;
-                }
-
-                String name = subdirs[i].getName();
-
-                if (LOCAL_LOGV) {
-                    Log.v(TAG, "Found dir " + subdirs[i].getAbsolutePath());
-                    Log.v(TAG, "name = " + name);
-                }
-
-                // Don't create a fake provider if a real provider exists
-                if (LocationProviderImpl.getProvider(name) == null) {
-                    LocationProviderImpl provider = null;
-                    try {
-                        File classFile = new File(subdirs[i], "class");
-                        // Look for a 'class' file
-                        provider = LocationProviderImpl.loadFromClass(classFile);
-
-                        // Look for an 'kml', 'nmea', or 'track' file
-                        if (provider == null) {
-                            // Load properties from 'properties' file, if present
-                            File propertiesFile = new File(subdirs[i], "properties");
-
-                            if (propertiesFile.exists()) {
-                                provider = new TrackProvider(name);
-                                ((TrackProvider)provider).readProperties(propertiesFile);
-
-                                File kmlFile = new File(subdirs[i], "kml");
-                                if (kmlFile.exists()) {
-                                    ((TrackProvider) provider).readKml(kmlFile);
-                                } else {
-                                    File nmeaFile = new File(subdirs[i], "nmea");
-                                    if (nmeaFile.exists()) {
-                                        ((TrackProvider) provider).readNmea(name, nmeaFile);
-                                    } else {
-                                        File trackFile = new File(subdirs[i], "track");
-                                        if (trackFile.exists()) {
-                                            ((TrackProvider) provider).readTrack(trackFile);
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        if (provider != null) {
-                            LocationProviderImpl.addProvider(provider);
-                        }
-                        // Grab the initial location of a TrackProvider and
-                        // store it as the last known location for that provider
-                        if (provider instanceof TrackProvider) {
-                            TrackProvider tp = (TrackProvider) provider;
-                            mLastKnownLocation.put(tp.getName(), tp.getInitialLocation());
-                        }
-                    } catch (Exception e) {
-                        Log.e(TAG, "Exception loading provder " + name, e);
-                    }
-                }
-            }
-        }
-
         updateProvidersLocked();
     }
 
@@ -550,118 +548,94 @@
     public LocationManagerService(Context context) {
         super();
         mContext = context;
-        mLocationHandler = new LocationWorkerHandler();
+
+        Thread thread = new Thread(null, this, "LocationManagerService");
+        thread.start();
 
         if (LOCAL_LOGV) {
             Log.v(TAG, "Constructed LocationManager Service");
         }
+    }
 
+    private void initialize() {
         // Alarm manager, needs to be done before calling loadProviders() below
-        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
         // Create a wake lock, needs to be done before calling loadProviders() below
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
         
-        // Battery statistics service to be notified when GPS turns on or off
-        mBatteryStats = BatteryStatsService.getService();
-
         // Load providers
         loadProviders();
 
-        // Listen for Radio changes
-        mTelephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
-        mTelephonyManager.listen(mPhoneStateListener,
-                PhoneStateListener.LISTEN_CELL_LOCATION |
-                PhoneStateListener.LISTEN_SIGNAL_STRENGTH |
-                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
-
         // Register for Network (Wifi or Mobile) updates
         NetworkStateBroadcastReceiver networkReceiver = new NetworkStateBroadcastReceiver();
         IntentFilter networkIntentFilter = new IntentFilter();
-        networkIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
-        networkIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         networkIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         networkIntentFilter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
-        context.registerReceiver(networkReceiver, networkIntentFilter);
+        mContext.registerReceiver(networkReceiver, networkIntentFilter);
 
         // Register for power updates
         PowerStateBroadcastReceiver powerStateReceiver = new PowerStateBroadcastReceiver();
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(ALARM_INTENT);
-        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
-        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
-        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
-        context.registerReceiver(powerStateReceiver, intentFilter);
+        mContext.registerReceiver(powerStateReceiver, intentFilter);
 
-        // Get the wifi manager
-        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-
-        // Create a wifi lock for future use
-        mWifiLock = getWifiWakelockLocked();
+        // listen for settings changes
+        ContentResolver resolver = mContext.getContentResolver();
+        Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
+                "(" + Settings.System.NAME + "=?)",
+                new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
+                null);
+        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
+        SettingsObserver settingsObserver = new SettingsObserver();
+        mSettings.addObserver(settingsObserver);
     }
 
-    public void setInstallCallback(InstallCallback callback) {
-        synchronized (mLocationListeners) {
-            mLocationHandler.removeMessages(MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER);
-            Message m = Message.obtain(mLocationHandler, 
-                    MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER, callback);
-            mLocationHandler.sendMessageAtFrontOfQueue(m);
+    public void run()
+    {
+        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+        Looper.prepare();
+        mLocationHandler = new LocationWorkerHandler();
+        initialize();
+        Looper.loop();
+    }
+
+    public void setNetworkLocationProvider(ILocationProvider provider) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                "Installing location providers outside of the system is not supported");
         }
-    }
 
-    public void setNetworkLocationProvider(INetworkLocationProvider provider) {
-        synchronized (mLocationListeners) {
-            mNetworkLocationInterface = provider;
-            provider.addListener(getPackageNames());
-            mNetworkLocationProvider = (LocationProviderImpl)provider;
+        synchronized (mLock) {
+            mNetworkLocationProvider =
+                    new LocationProviderProxy(LocationManager.NETWORK_PROVIDER, this, provider);
             LocationProviderImpl.addProvider(mNetworkLocationProvider);
             updateProvidersLocked();
             
             // notify NetworkLocationProvider of any events it might have missed
-            synchronized (mLocationListeners) {
-                mNetworkLocationProvider.updateNetworkState(mNetworkState);
-                mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
-                mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
-
-                if (mLastCellState != null) {
-                    if (mCollector != null) {
-                        mCollector.updateCellState(mLastCellState);
-                    }
-                    mNetworkLocationProvider.updateCellState(mLastCellState);
-                }
-
-                // There might be an existing wifi scan available
-                if (mWifiManager != null) {
-                    List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
-                    if (wifiScanResults != null && wifiScanResults.size() != 0) {
-                        mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
-                        if (mCollector != null) {
-                            mCollector.updateWifiScanResults(wifiScanResults);
-                        }
-                    }
-                }
-            }
+            mNetworkLocationProvider.updateNetworkState(mNetworkState);
         }
     }
 
     public void setLocationCollector(ILocationCollector collector) {
-        synchronized (mLocationListeners) {
-            mCollector = collector;
-            if (mGpsLocationProvider != null) {
-                mGpsLocationProvider.setLocationCollector(mCollector);
-            }
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                "Installing location collectors outside of the system is not supported");
         }
+
+        mCollector = collector;
     }
 
-    private WifiManager.WifiLock getWifiWakelockLocked() {
-        if (mWifiLock == null && mWifiManager != null) {
-            mWifiLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, WIFILOCK_KEY);
-            mWifiLock.setReferenceCounted(false);
+    public void setGeocodeProvider(IGeocodeProvider provider) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                "Installing location providers outside of the system is not supported");
         }
-        return mWifiLock;
+
+        mGeocodeProvider = provider;
     }
 
     private boolean isAllowedBySettingsLocked(String provider) {
@@ -712,15 +686,9 @@
         return true;
     }
 
-    private String[] getPackageNames() {
-        // Since a single UID may correspond to multiple packages, this can only be used as an
-        // approximation for tracking
-        return mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
-    }
-
     public List<String> getAllProviders() {
         try {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 return _getAllProvidersLocked();
             }
         } catch (SecurityException se) {
@@ -735,10 +703,10 @@
         if (LOCAL_LOGV) {
             Log.v(TAG, "getAllProviders");
         }
-        List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
+        ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
         ArrayList<String> out = new ArrayList<String>(providers.size());
-
-        for (LocationProviderImpl p : providers) {
+        for (int i = providers.size() - 1; i >= 0; i--) {
+            LocationProviderImpl p = providers.get(i);
             out.add(p.getName());
         }
         return out;
@@ -746,7 +714,7 @@
 
     public List<String> getProviders(boolean enabledOnly) {
         try {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 return _getProvidersLocked(enabledOnly);
             }
         } catch (SecurityException se) {
@@ -761,10 +729,10 @@
         if (LOCAL_LOGV) {
             Log.v(TAG, "getProviders");
         }
-        List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
-        ArrayList<String> out = new ArrayList<String>();
-
-        for (LocationProviderImpl p : providers) {
+        ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
+        ArrayList<String> out = new ArrayList<String>(providers.size());
+        for (int i = providers.size() - 1; i >= 0; i--) {
+            LocationProviderImpl p = providers.get(i);
             String name = p.getName();
             if (isAllowedProviderSafe(name)) {
                 if (enabledOnly && !isAllowedBySettingsLocked(name)) {
@@ -776,24 +744,14 @@
         return out;
     }
 
-    public void updateProviders() {
-        synchronized (mLocationListeners) {
-            updateProvidersLocked();
-        }
-    }
-
     private void updateProvidersLocked() {
-        for (LocationProviderImpl p : LocationProviderImpl.getProviders()) {
+        ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
+        for (int i = providers.size() - 1; i >= 0; i--) {
+            LocationProviderImpl p = providers.get(i);
             boolean isEnabled = p.isEnabled();
             String name = p.getName();
             boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
 
-            // Collection is only allowed when network provider is being used
-            if (mCollector != null &&
-                    p.getName().equals(LocationManager.NETWORK_PROVIDER)) {
-                mCollector.updateNetworkProviderStatus(shouldBeEnabled);
-            }
-
             if (isEnabled && !shouldBeEnabled) {
                 updateProviderListenersLocked(name, false);
             } else if (!isEnabled && shouldBeEnabled) {
@@ -819,29 +777,11 @@
             for (int i=0; i<N; i++) {
                 UpdateRecord record = records.get(i);
                 // Sends a notification message to the receiver
-                try {
-                    Receiver receiver = record.mReceiver;
-                    if (receiver.isListener()) {
-                        if (enabled) {
-                            receiver.getListener().onProviderEnabled(provider);
-                        } else {
-                            receiver.getListener().onProviderDisabled(provider);
-                        }
-                    } else {
-                        Intent providerIntent = new Intent();
-                        providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
-                        try {
-                            receiver.getPendingIntent().send(mContext, 0,
-                                 providerIntent, null, null);
-                        } catch (PendingIntent.CanceledException e) {
-                            if (deadReceivers == null) {
-                                deadReceivers = new ArrayList<Receiver>();
-                                deadReceivers.add(receiver);
-                            }
-                        }
+                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
+                    if (deadReceivers == null) {
+                        deadReceivers = new ArrayList<Receiver>();
+                        deadReceivers.add(record.mReceiver);
                     }
-                } catch (RemoteException e) {
-                    // The death link will clean this up.
                 }
                 listeners++;
             }
@@ -858,24 +798,12 @@
             if (listeners > 0) {
                 p.setMinTime(getMinTimeLocked(provider));
                 p.enableLocationTracking(true);
-                updateWakelockStatusLocked(mScreenOn);
+                updateWakelockStatusLocked();
             }
         } else {
             p.enableLocationTracking(false);
-            if (p == mGpsLocationProvider) {
-                mGpsNavigating = false;
-                reportStopGpsLocked();
-            }
             p.disable();
-            updateWakelockStatusLocked(mScreenOn);
-        }
-
-        if (enabled && listeners > 0) {
-            mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
-            Message m = Message.obtain(mLocationHandler, MESSAGE_HEARTBEAT, provider);
-            mLocationHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
-        } else {
-            mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
+            updateWakelockStatusLocked();
         }
     }
 
@@ -896,19 +824,19 @@
         final long mMinTime;
         final float mMinDistance;
         final int mUid;
-        final String[] mPackages;
+        Location mLastFixBroadcast;
+        long mLastStatusBroadcast;
 
         /**
          * Note: must be constructed with lock held.
          */
         UpdateRecord(String provider, long minTime, float minDistance,
-            Receiver receiver, int uid, String[] packages) {
+            Receiver receiver, int uid) {
             mProvider = provider;
             mReceiver = receiver;
             mMinTime = minTime;
             mMinDistance = minDistance;
             mUid = uid;
-            mPackages = packages;
 
             ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
             if (records == null) {
@@ -940,33 +868,77 @@
             pw.println(prefix + this);
             pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver);
             pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance);
-            StringBuilder sb = new StringBuilder();
-            if (mPackages != null) {
-                for (int i=0; i<mPackages.length; i++) {
-                    if (i > 0) sb.append(", ");
-                    sb.append(mPackages[i]);
-                }
-            }
-            pw.println(prefix + "mUid=" + mUid + " mPackages=" + sb);
+            pw.println(prefix + "mUid=" + mUid);
+            pw.println(prefix + "mLastFixBroadcast:");
+            mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
+            pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
         }
         
         /**
          * Calls dispose().
          */
         @Override protected void finalize() {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 disposeLocked();
             }
         }
     }
 
+    private Receiver getReceiver(ILocationListener listener) {
+        IBinder binder = listener.asBinder();
+        Receiver receiver = mReceivers.get(binder);
+        if (receiver == null) {
+            receiver = new Receiver(listener);
+            mReceivers.put(binder, receiver);
+
+            try {
+                if (receiver.isListener()) {
+                    receiver.getListener().asBinder().linkToDeath(receiver, 0);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "linkToDeath failed:", e);
+                return null;
+            }
+        }
+        return receiver;
+    }
+
+    private Receiver getReceiver(PendingIntent intent) {
+        Receiver receiver = mReceivers.get(intent);
+        if (receiver == null) {
+            receiver = new Receiver(intent);
+            mReceivers.put(intent, receiver);
+        }
+        return receiver;
+    }
+
+    private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) {
+        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
+        if (records != null) {
+            for (int i = records.size() - 1; i >= 0; i--) {
+                UpdateRecord record = records.get(i);
+                if (record.mUid == uid && record.mReceiver != excludedReceiver) {
+                    return true;
+                }
+           }
+        }
+        if (LocationManager.GPS_PROVIDER.equals(provider) ||
+                LocationManager.NETWORK_PROVIDER.equals(provider)) {
+            for (ProximityAlert alert : mProximityAlerts.values()) {
+                if (alert.mUid == uid) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     public void requestLocationUpdates(String provider,
         long minTime, float minDistance, ILocationListener listener) {
 
         try {
-            synchronized (mLocationListeners) {
-                requestLocationUpdatesLocked(provider, minTime, minDistance,
-                    new Receiver(listener, Binder.getCallingUid()));
+            synchronized (mLock) {
+                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener));
             }
         } catch (SecurityException se) {
             throw se;
@@ -978,9 +950,8 @@
     public void requestLocationUpdatesPI(String provider,
             long minTime, float minDistance, PendingIntent intent) {
         try {
-            synchronized (mLocationListeners) {
-                requestLocationUpdatesLocked(provider, minTime, minDistance,
-                        new Receiver(intent, Binder.getCallingUid()));
+            synchronized (mLock) {
+                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent));
             }
         } catch (SecurityException se) {
             throw se;
@@ -1002,62 +973,30 @@
 
         checkPermissionsSafe(provider);
 
-        String[] packages = getPackageNames();
-
         // so wakelock calls will succeed
         final int callingUid = Binder.getCallingUid();
+        boolean newUid = !providerHasListener(provider, callingUid, null);
         long identity = Binder.clearCallingIdentity();
         try {
-            UpdateRecord r = new UpdateRecord(provider, minTime, minDistance,
-                    receiver, callingUid, packages);
-            if (!mListeners.contains(receiver)) {
-                try {
-                    if (receiver.isListener()) {
-                        receiver.getListener().asBinder().linkToDeath(receiver, 0);
-                    }
-                    mListeners.add(receiver);
-                } catch (RemoteException e) {
-                    return;
-                }
-            }
-
-            HashMap<String,UpdateRecord> records = mLocationListeners.get(receiver);
-            if (records == null) {
-                records = new HashMap<String,UpdateRecord>();
-                mLocationListeners.put(receiver, records);
-            }
-            UpdateRecord oldRecord = records.put(provider, r);
+            UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid);
+            UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
             if (oldRecord != null) {
                 oldRecord.disposeLocked();
             }
 
+            if (newUid) {
+                impl.addListener(callingUid);
+            }
+
             boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
             if (isProviderEnabled) {
                 long minTimeForProvider = getMinTimeLocked(provider);
                 impl.setMinTime(minTimeForProvider);
                 impl.enableLocationTracking(true);
-                updateWakelockStatusLocked(mScreenOn);
-
-                if (provider.equals(LocationManager.GPS_PROVIDER)) {
-                    if (mGpsNavigating) {
-                        updateReportedGpsLocked();
-                    }
-                }
-                
-                // Clear heartbeats if any before starting a new one
-                mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
-                Message m = Message.obtain(mLocationHandler, MESSAGE_HEARTBEAT, provider);
-                mLocationHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
+                updateWakelockStatusLocked();
             } else {
-                try {
-                    // Notify the listener that updates are currently disabled
-                    if (receiver.isListener()) {
-                        receiver.getListener().onProviderDisabled(provider);
-                    }
-                } catch(RemoteException e) {
-                    Log.w(TAG, "RemoteException calling onProviderDisabled on " +
-                            receiver.getListener());
-                }
+                // Notify the listener that updates are currently disabled
+                receiver.callProviderEnabledLocked(provider, false);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -1066,8 +1005,8 @@
 
     public void removeUpdates(ILocationListener listener) {
         try {
-            synchronized (mLocationListeners) {
-                removeUpdatesLocked(new Receiver(listener, Binder.getCallingUid()));
+            synchronized (mLock) {
+                removeUpdatesLocked(getReceiver(listener));
             }
         } catch (SecurityException se) {
             throw se;
@@ -1078,8 +1017,8 @@
 
     public void removeUpdatesPI(PendingIntent intent) {
         try {
-            synchronized (mLocationListeners) {
-                removeUpdatesLocked(new Receiver(intent, Binder.getCallingUid()));
+            synchronized (mLock) {
+                removeUpdatesLocked(getReceiver(intent));
             }
         } catch (SecurityException se) {
             throw se;
@@ -1097,23 +1036,21 @@
         final int callingUid = Binder.getCallingUid();
         long identity = Binder.clearCallingIdentity();
         try {
-            int idx = mListeners.indexOf(receiver);
-            if (idx >= 0) {
-                Receiver myReceiver = mListeners.remove(idx);
-                if (myReceiver.isListener()) {
-                    myReceiver.getListener().asBinder().unlinkToDeath(myReceiver, 0);
-                }
+            if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
+                receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
             }
 
             // Record which providers were associated with this listener
             HashSet<String> providers = new HashSet<String>();
-            HashMap<String,UpdateRecord> oldRecords = mLocationListeners.get(receiver);
+            HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords;
             if (oldRecords != null) {
                 // Call dispose() on the obsolete update records.
                 for (UpdateRecord record : oldRecords.values()) {
-                    if (record.mProvider.equals(LocationManager.NETWORK_PROVIDER)) {
-                        if (mNetworkLocationInterface != null) {
-                            mNetworkLocationInterface.removeListener(record.mPackages);
+                    if (!providerHasListener(record.mProvider, callingUid, receiver)) {
+                        LocationProviderImpl impl =
+                                LocationProviderImpl.getProvider(record.mProvider);
+                        if (impl != null) {
+                            impl.removeListener(callingUid);
                         }
                     }
                     record.disposeLocked();
@@ -1121,10 +1058,6 @@
                 // Accumulate providers
                 providers.addAll(oldRecords.keySet());
             }
-            
-            mLocationListeners.remove(receiver);
-            mLastFixBroadcast.remove(receiver);
-            mLastStatusBroadcast.remove(receiver);
 
             // See if the providers associated with this listener have any
             // other listeners; if one does, inform it of the new smallest minTime
@@ -1146,17 +1079,12 @@
                     if (hasOtherListener) {
                         p.setMinTime(getMinTimeLocked(provider));
                     } else {
-                        mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
                         p.enableLocationTracking(false);
                     }
-                    
-                    if (p == mGpsLocationProvider && mGpsNavigating) {
-                        updateReportedGpsLocked();
-                    }
                 }
             }
 
-            updateWakelockStatusLocked(mScreenOn);
+            updateWakelockStatusLocked();
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1181,7 +1109,7 @@
     }
 
     public void removeGpsStatusListener(IGpsStatusListener listener) {
-        synchronized (mLocationListeners) {
+        synchronized (mLock) {
             mGpsLocationProvider.removeGpsStatusListener(listener);
         }
     }
@@ -1195,7 +1123,7 @@
             throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
         }
 
-        synchronized (mLocationListeners) {
+        synchronized (mLock) {
             LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
             if (provider == null) {
                 return false;
@@ -1263,7 +1191,7 @@
     }
 
     // Listener for receiving locations to trigger proximity alerts
-    class ProximityListener extends ILocationListener.Stub {
+    class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
 
         boolean isGpsAvailable = false;
 
@@ -1300,7 +1228,14 @@
                         Intent enteredIntent = new Intent();
                         enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
                         try {
-                            intent.send(mContext, 0, enteredIntent, null, null);
+                            synchronized (mLock) {
+                                // synchronize to ensure incrementPendingBroadcastsLocked()
+                                // is called before decrementPendingBroadcasts()
+                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
+                                // call this after broadcasting so we do not increment
+                                // if we throw an exeption.
+                                incrementPendingBroadcastsLocked();
+                            }
                         } catch (PendingIntent.CanceledException e) {
                             if (LOCAL_LOGV) {
                                 Log.v(TAG, "Canceled proximity alert: " + alert, e);
@@ -1318,7 +1253,14 @@
                         Intent exitedIntent = new Intent();
                         exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
                         try {
-                            intent.send(mContext, 0, exitedIntent, null, null);
+                            synchronized (mLock) {
+                                // synchronize to ensure incrementPendingBroadcastsLocked()
+                                // is called before decrementPendingBroadcasts()
+                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
+                                // call this after broadcasting so we do not increment
+                                // if we throw an exeption.
+                                incrementPendingBroadcastsLocked();
+                            }
                         } catch (PendingIntent.CanceledException e) {
                             if (LOCAL_LOGV) {
                                 Log.v(TAG, "Canceled proximity alert: " + alert, e);
@@ -1371,12 +1313,17 @@
                 isGpsAvailable = false;
             }
         }
+
+        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
+                int resultCode, String resultData, Bundle resultExtras) {
+            decrementPendingBroadcasts();
+        }
     }
 
     public void addProximityAlert(double latitude, double longitude,
         float radius, long expiration, PendingIntent intent) {
         try {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
             }
         } catch (SecurityException se) {
@@ -1408,28 +1355,27 @@
                 latitude, longitude, radius, expiration, intent);
         mProximityAlerts.put(intent, alert);
 
-        if (mProximityListener == null) {
-            mProximityListener = new Receiver(new ProximityListener(), -1);
+        if (mProximityReceiver == null) {
+            mProximityListener = new ProximityListener();
+            mProximityReceiver = new Receiver(mProximityListener);
 
             LocationProvider provider = LocationProviderImpl.getProvider(
                 LocationManager.GPS_PROVIDER);
             if (provider != null) {
-                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener);
+                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
             }
 
             provider =
                 LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER);
             if (provider != null) {
-                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener);
+                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
             }
-        } else if (mGpsNavigating) {
-            updateReportedGpsLocked();
         }
     }
 
     public void removeProximityAlert(PendingIntent intent) {
         try {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                removeProximityAlertLocked(intent);
             }
         } catch (SecurityException se) {
@@ -1446,10 +1392,9 @@
 
         mProximityAlerts.remove(intent);
         if (mProximityAlerts.size() == 0) {
-            removeUpdatesLocked(mProximityListener);
+            removeUpdatesLocked(mProximityReceiver);
+            mProximityReceiver = null;
             mProximityListener = null;
-        } else if (mGpsNavigating) {
-            updateReportedGpsLocked();
         }
      }
 
@@ -1460,7 +1405,7 @@
      */
     public Bundle getProviderInfo(String provider) {
         try {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 return _getProviderInfoLocked(provider);
             }
         } catch (SecurityException se) {
@@ -1495,7 +1440,7 @@
 
     public boolean isProviderEnabled(String provider) {
         try {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 return _isProviderEnabledLocked(provider);
             }
         } catch (SecurityException se) {
@@ -1506,6 +1451,12 @@
         }
     }
 
+    public void setLocation(Location location) {
+        mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
+        Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
+        mLocationHandler.sendMessageAtFrontOfQueue(m);
+    }
+
     private boolean _isProviderEnabledLocked(String provider) {
         checkPermissionsSafe(provider);
 
@@ -1518,7 +1469,7 @@
 
     public Location getLastKnownLocation(String provider) {
         try {
-            synchronized (mLocationListeners) {
+            synchronized (mLock) {
                 return _getLastKnownLocationLocked(provider);
             }
         } catch (SecurityException se) {
@@ -1576,7 +1527,8 @@
         return true;
     }
 
-    private void handleLocationChangedLocked(String provider) {
+    private void handleLocationChangedLocked(Location location) {
+        String provider = location.getProvider();
         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
         if (records == null || records.size() == 0) {
             return;
@@ -1587,68 +1539,28 @@
             return;
         }
 
-        // Get location object
-        Location loc = mLocationsByProvider.get(provider);
-        if (loc == null) {
-            loc = new Location(provider);
-            mLocationsByProvider.put(provider, loc);
-        } else {
-            loc.reset();
-        }
-
-        // Use the mock location if available
-        Location mockLoc = mMockProviderLocation.get(provider);
-        boolean locationValid;
-        if (mockLoc != null) {
-            locationValid = true;
-            loc.set(mockLoc);
-        } else {
-            locationValid = p.getLocation(loc);
-        }
-
         // Update last known location for provider
-        if (locationValid) {
-            Location location = mLastKnownLocation.get(provider);
-            if (location == null) {
-                mLastKnownLocation.put(provider, new Location(loc));
-            } else {
-                location.set(loc);
-            }
-            writeLastKnownLocationLocked(provider, loc);
+        Location lastLocation = mLastKnownLocation.get(provider);
+        if (lastLocation == null) {
+            mLastKnownLocation.put(provider, new Location(location));
+        } else {
+            lastLocation.set(location);
+        }
+        writeLastKnownLocationLocked(provider, location);
 
-            if (p instanceof INetworkLocationProvider) {
-                mWakeLockNetworkReceived = true;
-            } else if (p instanceof GpsLocationProvider) {
-                // Gps location received signal is in NetworkStateBroadcastReceiver
-            }
+        if (LocationManager.NETWORK_PROVIDER.equals(p.getName())) {
+            mWakeLockNetworkReceived = true;
+        } else if (p instanceof GpsLocationProvider) {
+            // Gps location received signal is in NetworkStateBroadcastReceiver
         }
 
         // Fetch latest status update time
         long newStatusUpdateTime = p.getStatusUpdateTime();
 
-        // Override real time with mock time if present
-        Long mockStatusUpdateTime = mMockProviderStatusUpdateTime.get(provider);
-        if (mockStatusUpdateTime != null) {
-            newStatusUpdateTime = mockStatusUpdateTime.longValue();
-        }
-
-        // Get latest status
+       // Get latest status
         Bundle extras = new Bundle();
         int status = p.getStatus(extras);
 
-        // Override status with mock status if present
-        Integer mockStatus = mMockProviderStatus.get(provider);
-        if (mockStatus != null) {
-            status = mockStatus.intValue();
-        }
-
-        // Override extras with mock extras if present
-        Bundle mockExtras = mMockProviderStatusExtras.get(provider);
-        if (mockExtras != null) {
-            extras.clear();
-            extras.putAll(mockExtras);
-        }
-
         ArrayList<Receiver> deadReceivers = null;
         
         // Broadcast location or status to all listeners
@@ -1657,44 +1569,28 @@
             UpdateRecord r = records.get(i);
             Receiver receiver = r.mReceiver;
 
-            // Broadcast location only if it is valid
-            if (locationValid) {
-                HashMap<String,Location> map = mLastFixBroadcast.get(receiver);
-                if (map == null) {
-                    map = new HashMap<String,Location>();
-                    mLastFixBroadcast.put(receiver, map);
+            Location lastLoc = r.mLastFixBroadcast;
+            if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
+                if (lastLoc == null) {
+                    lastLoc = new Location(location);
+                    r.mLastFixBroadcast = lastLoc;
+                } else {
+                    lastLoc.set(location);
                 }
-                Location lastLoc = map.get(provider);
-                if ((lastLoc == null) || shouldBroadcastSafe(loc, lastLoc, r)) {
-                    if (lastLoc == null) {
-                        lastLoc = new Location(loc);
-                        map.put(provider, lastLoc);
-                    } else {
-                        lastLoc.set(loc);
+                if (!receiver.callLocationChangedLocked(location)) {
+                    Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
+                    if (deadReceivers == null) {
+                        deadReceivers = new ArrayList<Receiver>();
                     }
-                    if (!receiver.callLocationChangedLocked(loc)) {
-                        Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
-                        if (deadReceivers == null) {
-                            deadReceivers = new ArrayList<Receiver>();
-                        }
-                        deadReceivers.add(receiver);
-                    }
+                    deadReceivers.add(receiver);
                 }
             }
 
-            // Broadcast status message
-            HashMap<String,Long> statusMap = mLastStatusBroadcast.get(receiver);
-            if (statusMap == null) {
-                statusMap = new HashMap<String,Long>();
-                mLastStatusBroadcast.put(receiver, statusMap);
-            }
-            long prevStatusUpdateTime =
-                (statusMap.get(provider) != null) ? statusMap.get(provider) : 0;
-
+            long prevStatusUpdateTime = r.mLastStatusBroadcast;
             if ((newStatusUpdateTime > prevStatusUpdateTime) &&
                 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
 
-                statusMap.put(provider, newStatusUpdateTime);
+                r.mLastStatusBroadcast = newStatusUpdateTime;
                 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
                     Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
                     if (deadReceivers == null) {
@@ -1719,70 +1615,28 @@
         @Override
         public void handleMessage(Message msg) {
             try {
-                if (msg.what == MESSAGE_HEARTBEAT) {
-                    // log("LocationWorkerHandler: Heartbeat!");
+                if (msg.what == MESSAGE_LOCATION_CHANGED) {
+                    // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
 
-                    synchronized (mLocationListeners) {
-                        String provider = (String) msg.obj;
+                    synchronized (mLock) {
+                        Location location = (Location) msg.obj;
+
+                        if (mCollector != null && 
+                                LocationManager.GPS_PROVIDER.equals(location.getProvider())) {
+                            try {
+                                mCollector.updateLocation(location);
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "mCollector.updateLocation failed");
+                            }
+                        }
+
+                        String provider = location.getProvider();
                         if (!isAllowedBySettingsLocked(provider)) {
                             return;
                         }
 
-                        // Process the location fix if the screen is on or we're holding a wakelock
-                        if (mScreenOn || (mWakeLockAcquireTime != 0)) {
-                            handleLocationChangedLocked(provider);
-                        }
-
-                        // If it continues to have listeners
-                        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
-                        if (records != null && records.size() > 0) {
-                            Message m = Message.obtain(this, MESSAGE_HEARTBEAT, provider);
-                            sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
-                        }
-
-                        if ((mWakeLockAcquireTime != 0) &&
-                            (SystemClock.elapsedRealtime() - mWakeLockAcquireTime
-                                > MAX_TIME_FOR_WAKE_LOCK)) {
-    
-                            removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
-                            removeMessages(MESSAGE_RELEASE_WAKE_LOCK);
-    
-                            log("LocationWorkerHandler: Exceeded max time for wake lock");
-                            Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK);
-                            sendMessageAtFrontOfQueue(m);
-    
-                        } else if (mWakeLockAcquireTime != 0 &&
-                            mWakeLockGpsReceived && mWakeLockNetworkReceived) {
-    
-                            removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
-                            removeMessages(MESSAGE_RELEASE_WAKE_LOCK);
-    
-                            log("LocationWorkerHandler: Locations received.");
-                            mWakeLockAcquireTime = 0;
-                            Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK);
-                            sendMessageDelayed(m, TIME_AFTER_WAKE_LOCK);
-                        }
-                    }
-
-                } else if (msg.what == MESSAGE_ACQUIRE_WAKE_LOCK) {
-                    log("LocationWorkerHandler: Acquire");
-                    synchronized (mLocationListeners) {
-                        acquireWakeLockLocked();
-                    }
-                } else if (msg.what == MESSAGE_RELEASE_WAKE_LOCK) {
-                    log("LocationWorkerHandler: Release");
-
-                    // Update wakelock status so the next alarm is set before releasing wakelock
-                    synchronized (mLocationListeners) {
-                        updateWakelockStatusLocked(mScreenOn);
-                        releaseWakeLockLocked();
-                    }
-                } else if (msg.what == MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER) {
-                    synchronized (mLocationListeners) {
-                        Log.d(TAG, "installing network location provider");
-                        INetworkLocationManager.InstallCallback callback =
-                                (INetworkLocationManager.InstallCallback)msg.obj;
-                        callback.installNetworkLocationProvider(LocationManagerService.this);
+                        handleLocationChangedLocked(location);
+                        updateWakelockStatusLocked();
                     }
                 }
             } catch (Exception e) {
@@ -1792,159 +1646,22 @@
         }
     }
 
-    class CellLocationUpdater extends Thread {
-        CellLocation mNextLocation;
-        
-        CellLocationUpdater() {
-            super("CellLocationUpdater");
-        }
-        
-        @Override
-        public void run() {
-            int curAsu = -1;
-            CellLocation curLocation = null;
-            
-            while (true) {
-                // See if there is more work to do...
-                synchronized (mLocationListeners) {
-                    if (curLocation == mNextLocation) {
-                        mCellLocationUpdater = null;
-                        break;
-                    }
-                    
-                    curLocation = mNextLocation;
-                    if (curLocation == null) {
-                        mCellLocationUpdater = null;
-                        break;
-                    }
-                    
-                    curAsu = mLastSignalStrength;
-                    
-                    mNextLocation = null;
-                }
-                
-                try {
-                    // Gets cell state.  This can block so must be done without
-                    // locks held.
-                    CellState cs = new CellState(mTelephonyManager, curLocation, curAsu);
-                    
-                    synchronized (mLocationListeners) {
-                        mLastCellState = cs;
-        
-                        cs.updateSignalStrength(mLastSignalStrength);
-                        cs.updateRadioType(mLastRadioType);
-                        
-                        // Notify collector
-                        if (mCollector != null) {
-                            mCollector.updateCellState(cs);
-                        }
-    
-                        // Updates providers
-                        List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
-                        for (LocationProviderImpl provider : providers) {
-                            if (provider.requiresCell()) {
-                                provider.updateCellState(cs);
-                            }
-                        }
-                    }
-                } catch (RuntimeException e) {
-                    Log.e(TAG, "Exception in PhoneStateListener.onCellLocationChanged:", e);
-                }
-            }
-        }
-    }
-    
-    CellLocationUpdater mCellLocationUpdater = null;
-    CellState mLastCellState = null;
-    int mLastSignalStrength = -1;
-    int mLastRadioType = -1;
-    
-    PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
-
-        @Override
-        public void onCellLocationChanged(CellLocation cellLocation) {
-            synchronized (mLocationListeners) {
-                if (mCellLocationUpdater == null) {
-                    mCellLocationUpdater = new CellLocationUpdater();
-                    mCellLocationUpdater.start();
-                }
-                mCellLocationUpdater.mNextLocation = cellLocation;
-            }
-        }
-
-        @Override
-        public void onSignalStrengthChanged(int asu) {
-            synchronized (mLocationListeners) {
-                mLastSignalStrength = asu;
-    
-                if (mLastCellState != null) {
-                    mLastCellState.updateSignalStrength(asu);
-                }
-            }
-        }
-
-        @Override
-        public void onDataConnectionStateChanged(int state) {
-            synchronized (mLocationListeners) {
-                // Get radio type
-                int radioType = mTelephonyManager.getNetworkType();
-                if (radioType == TelephonyManager.NETWORK_TYPE_GPRS ||
-                    radioType == TelephonyManager.NETWORK_TYPE_EDGE) {
-                    radioType = CellState.RADIO_TYPE_GPRS;
-                } else if (radioType == TelephonyManager.NETWORK_TYPE_UMTS) {
-                    radioType = CellState.RADIO_TYPE_WCDMA;
-                }
-                mLastRadioType = radioType;
-
-                if (mLastCellState != null) {
-                    mLastCellState.updateRadioType(radioType);
-                }
-            }
-        }
-    };
-
     private class PowerStateBroadcastReceiver extends BroadcastReceiver {
         @Override public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
 
             if (action.equals(ALARM_INTENT)) {
-                synchronized (mLocationListeners) {
+                synchronized (mLock) {
                     log("PowerStateBroadcastReceiver: Alarm received");
-                    mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
                     // Have to do this immediately, rather than posting a
                     // message, so we execute our code while the system
                     // is holding a wake lock until the alarm broadcast
                     // is finished.
                     acquireWakeLockLocked();
                 }
-
-            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
-                log("PowerStateBroadcastReceiver: Screen off");
-                synchronized (mLocationListeners) {
-                    updateWakelockStatusLocked(false);
-                }
-
-            } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
-                log("PowerStateBroadcastReceiver: Screen on");
-                synchronized (mLocationListeners) {
-                    updateWakelockStatusLocked(true);
-                }
-
-            } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
-                log("PowerStateBroadcastReceiver: Battery changed");
-                synchronized (mLocationListeners) {
-                    int scale = intent.getIntExtra(BATTERY_EXTRA_SCALE, 100);
-                    int level = intent.getIntExtra(BATTERY_EXTRA_LEVEL, 0);
-                    boolean plugged = intent.getIntExtra(BATTERY_EXTRA_PLUGGED, 0) != 0;
-    
-                    // Notify collector battery state
-                    if (mCollector != null) {
-                        mCollector.updateBatteryState(scale, level, plugged);
-                    }
-                }
             } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
                     || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
-                synchronized (mLocationListeners) {
+                synchronized (mLock) {
                     int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
                     if (uid >= 0) {
                         ArrayList<Receiver> removedRecs = null;
@@ -1992,25 +1709,7 @@
         @Override public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
 
-            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-
-                List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
-
-                if (wifiScanResults == null) {
-                    return;
-                }
-
-                // Notify provider and collector of Wifi scan results
-                synchronized (mLocationListeners) {
-                    if (mCollector != null) {
-                        mCollector.updateWifiScanResults(wifiScanResults);
-                    }
-                    if (mNetworkLocationInterface != null) {
-                        mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
-                    }
-                }
-
-            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                 boolean noConnectivity =
                     intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
                 if (!noConnectivity) {
@@ -2020,46 +1719,22 @@
                 }
 
                 // Notify location providers of current network state
-                synchronized (mLocationListeners) {
-                    List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
-                    for (LocationProviderImpl provider : providers) {
+                synchronized (mLock) {
+                    ArrayList<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
+                    for (int i = providers.size() - 1; i >= 0; i--) {
+                        LocationProviderImpl provider = providers.get(i);
                         if (provider.requiresNetwork()) {
                             provider.updateNetworkState(mNetworkState);
                         }
                     }
                 }
-
-            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-                int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                    WifiManager.WIFI_STATE_UNKNOWN);
-
-                if (state == WifiManager.WIFI_STATE_ENABLED) {
-                    mWifiEnabled = true;
-                } else if (state == WifiManager.WIFI_STATE_DISABLED) {
-                    mWifiEnabled = false;
-                } else {
-                    return;
-                }
-
-                // Notify network provider of current wifi enabled state
-                synchronized (mLocationListeners) {
-                    if (mNetworkLocationInterface != null) {
-                        mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
-                    }
-                }
-
             } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION)) {
 
                 final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED,
                     false);
 
-                synchronized (mLocationListeners) {
-                    if (enabled) {
-                        updateReportedGpsLocked();
-                        mGpsNavigating = true;
-                    } else {
-                        reportStopGpsLocked();
-                        mGpsNavigating = false;
+                synchronized (mLock) {
+                    if (!enabled) {
                         // When GPS is disabled, we are OK to release wake-lock
                         mWakeLockGpsReceived = true;
                     }
@@ -2071,12 +1746,12 @@
 
     // Wake locks
 
-    private void updateWakelockStatusLocked(boolean screenOn) {
-        log("updateWakelockStatus(): " + screenOn);
+    private void updateWakelockStatusLocked() {
+        log("updateWakelockStatus()");
 
         long callerId = Binder.clearCallingIdentity();
         
-        boolean needsLock = false;
+        boolean needsLock = (mPendingBroadcasts > 0);
         long minTime = Integer.MAX_VALUE;
 
         if (mNetworkLocationProvider != null && mNetworkLocationProvider.isLocationTracking()) {
@@ -2087,16 +1762,8 @@
         if (mGpsLocationProvider != null && mGpsLocationProvider.isLocationTracking()) {
             needsLock = true;
             minTime = Math.min(mGpsLocationProvider.getMinTime(), minTime);
-            if (screenOn) {
-                startGpsLocked();
-            } else if (mScreenOn && !screenOn) {
-                // We just turned the screen off so stop navigating
-                stopGpsLocked();
-            }
         }
 
-        mScreenOn = screenOn;
-
         PendingIntent sender =
             PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_INTENT), 0);
 
@@ -2104,7 +1771,7 @@
         log("Cancelling existing alarm");
         mAlarmManager.cancel(sender);
 
-        if (needsLock && !mScreenOn) {
+        if (needsLock) {
             long now = SystemClock.elapsedRealtime();
             mAlarmManager.set(
                 AlarmManager.ELAPSED_REALTIME_WAKEUP, now + minTime, sender);
@@ -2114,9 +1781,6 @@
             log("No need for alarm");
             mAlarmInterval = -1;
 
-            // Clear out existing wakelocks
-            mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK);
-            mLocationHandler.removeMessages(MESSAGE_RELEASE_WAKE_LOCK);
             releaseWakeLockLocked();
         }
         Binder.restoreCallingIdentity(callerId);
@@ -2158,131 +1822,11 @@
         mWakeLockAcquireTime = SystemClock.elapsedRealtime();
         log("Acquired wakelock");
 
-        // Start the gps provider
-        startGpsLocked();
-
-        // Acquire cell lock
-        if (mCellWakeLockAcquired) {
-            // Lock is already acquired
-        } else if (!mWakeLockNetworkReceived) {
-            mTelephonyManager.enableLocationUpdates();
-            mCellWakeLockAcquired = true;
-        } else {
-            mCellWakeLockAcquired = false;
+        if (mNetworkLocationProvider != null) {
+            mNetworkLocationProvider.wakeLockAcquired();
         }
-
-        // Notify NetworkLocationProvider
-        if (mNetworkLocationInterface != null) {
-            mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
-        }
-
-        // Acquire wifi lock
-        WifiManager.WifiLock wifiLock = getWifiWakelockLocked();
-        if (wifiLock != null) {
-            if (mWifiWakeLockAcquired) {
-                // Lock is already acquired
-            } else if (mWifiManager.isWifiEnabled() && !mWakeLockNetworkReceived) {
-                wifiLock.acquire();
-                mWifiWakeLockAcquired = true;
-            } else {
-                mWifiWakeLockAcquired = false;
-                Log.w(TAG, "acquireWakeLock(): Unable to get WiFi lock");
-            }
-        }
-    }
-
-    private boolean reportGpsUidLocked(int curSeq, int nextSeq, int uid) {
-        int seq = mReportedGpsUids.get(uid, -1);
-        if (seq == curSeq) {
-            // Already reported; propagate to next sequence.
-            mReportedGpsUids.put(uid, nextSeq);
-            return true;
-        } else if (seq != nextSeq) {
-            try {
-                // New UID; report it.
-                mBatteryStats.noteStartGps(uid);
-                mReportedGpsUids.put(uid, nextSeq);
-                return true;
-            } catch (RemoteException e) {
-            }
-        }
-        return false;
-    }
-    
-    private void updateReportedGpsLocked() {
-        if (mGpsLocationProvider == null) {
-            return;
-        }
-        
-        final String name = mGpsLocationProvider.getName();
-        final int curSeq = mReportedGpsSeq;
-        final int nextSeq = (curSeq+1) >= 0 ? (curSeq+1) : 0;
-        mReportedGpsSeq = nextSeq;
-        
-        ArrayList<UpdateRecord> urs = mRecordsByProvider.get(name);
-        int num = 0;
-        final int N = urs.size();
-        for (int i=0; i<N; i++) {
-            UpdateRecord ur = urs.get(i);
-            if (ur.mReceiver == mProximityListener) {
-                // We don't want the system to take the blame for this one.
-                continue;
-            }
-            if (reportGpsUidLocked(curSeq, nextSeq, ur.mUid)) {
-                num++;
-            }
-        }
-        
-        for (ProximityAlert pe : mProximityAlerts.values()) {
-            if (reportGpsUidLocked(curSeq, nextSeq, pe.mUid)) {
-                num++;
-            }
-        }
-        
-        if (num != mReportedGpsUids.size()) {
-            // The number of uids is processed is different than the
-            // array; report any that are no longer active.
-            for (int i=mReportedGpsUids.size()-1; i>=0; i--) {
-                if (mReportedGpsUids.valueAt(i) != nextSeq) {
-                    try {
-                        mBatteryStats.noteStopGps(mReportedGpsUids.keyAt(i));
-                    } catch (RemoteException e) {
-                    }
-                    mReportedGpsUids.removeAt(i);
-                }
-            }
-        }
-    }
-    
-    private void reportStopGpsLocked() {
-        int curSeq = mReportedGpsSeq;
-        for (int i=mReportedGpsUids.size()-1; i>=0; i--) {
-            if (mReportedGpsUids.valueAt(i) == curSeq) {
-                try {
-                    mBatteryStats.noteStopGps(mReportedGpsUids.keyAt(i));
-                } catch (RemoteException e) {
-                }
-            }
-        }
-        curSeq++;
-        if (curSeq < 0) curSeq = 0;
-        mReportedGpsSeq = curSeq;
-        mReportedGpsUids.clear();
-    }
-    
-    private void startGpsLocked() {
-        boolean gpsActive = (mGpsLocationProvider != null)
-                    && mGpsLocationProvider.isLocationTracking();
-        if (gpsActive) {
-            mGpsLocationProvider.startNavigating();
-        }
-    }
-
-    private void stopGpsLocked() {
-        boolean gpsActive = mGpsLocationProvider != null
-                    && mGpsLocationProvider.isLocationTracking();
-        if (gpsActive) {
-            mGpsLocationProvider.stopNavigating();
+        if (mGpsLocationProvider != null) {
+            mGpsLocationProvider.wakeLockAcquired();
         }
     }
 
@@ -2297,29 +1841,11 @@
     }
 
     private void releaseWakeLockXLocked() {
-        // Release wifi lock
-        WifiManager.WifiLock wifiLock = getWifiWakelockLocked();
-        if (wifiLock != null) {
-            if (mWifiWakeLockAcquired) {
-                wifiLock.release();
-                mWifiWakeLockAcquired = false;
-            }
+        if (mNetworkLocationProvider != null) {
+            mNetworkLocationProvider.wakeLockReleased();
         }
-
-        if (!mScreenOn) {
-            // Stop the gps
-            stopGpsLocked();
-        }
-
-        // Release cell lock
-        if (mCellWakeLockAcquired) {
-            mTelephonyManager.disableLocationUpdates();
-            mCellWakeLockAcquired = false;
-        }
-
-        // Notify NetworkLocationProvider
-        if (mNetworkLocationInterface != null) {
-            mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
+        if (mGpsLocationProvider != null) {
+            mGpsLocationProvider.wakeLockReleased();
         }
 
         // Release wake lock
@@ -2332,172 +1858,55 @@
         }
     }
 
-    // Geocoder
+    private void incrementPendingBroadcastsLocked() {
+        if (mPendingBroadcasts++ == 0) {
+            updateWakelockStatusLocked();
+        }
+    }
 
-    public String getFromLocation(double latitude, double longitude, int maxResults,
-        String language, String country, String variant, String appName, List<Address> addrs) {
-        synchronized (mLocationListeners) {
-            if (mNetworkLocationInterface != null) {
-                return mNetworkLocationInterface.getFromLocation(latitude, longitude, maxResults,
-                        language, country, variant, appName, addrs);
-            } else {
-                return null;
+    private void decrementPendingBroadcasts() {
+        synchronized (mLock) {
+            if (--mPendingBroadcasts == 0) {
+                updateWakelockStatusLocked();
             }
         }
     }
 
-    public String getFromLocationName(String locationName,
-        double lowerLeftLatitude, double lowerLeftLongitude,
-        double upperRightLatitude, double upperRightLongitude, int maxResults,
-        String language, String country, String variant, String appName, List<Address> addrs) {
-        synchronized (mLocationListeners) {
-            if (mNetworkLocationInterface != null) {
-                return mNetworkLocationInterface.getFromLocationName(locationName, lowerLeftLatitude, 
-                        lowerLeftLongitude, upperRightLatitude, upperRightLongitude, maxResults,
-                        language, country, variant, appName, addrs);
-            } else {
-                return null;
+    // Geocoder
+
+    public String getFromLocation(double latitude, double longitude, int maxResults,
+            String language, String country, String variant, String appName, List<Address> addrs) {
+        if (mGeocodeProvider != null) {
+            try {
+                return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, language, country,
+                        variant, appName,  addrs);
+            } catch (RemoteException e) {
+                Log.e(TAG, "getFromLocation failed", e);
             }
         }
+        return null;
+    }
+
+
+    public String getFromLocationName(String locationName,
+            double lowerLeftLatitude, double lowerLeftLongitude,
+            double upperRightLatitude, double upperRightLongitude, int maxResults,
+            String language, String country, String variant, String appName, List<Address> addrs) {
+
+        if (mGeocodeProvider != null) {
+            try {
+                return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
+                        lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
+                        maxResults, language, country, variant, appName, addrs);
+            } catch (RemoteException e) {
+                Log.e(TAG, "getFromLocationName failed", e);
+            }
+        }
+        return null;
     }
 
     // Mock Providers
 
-    class MockProvider extends LocationProviderImpl {
-        boolean mRequiresNetwork;
-        boolean mRequiresSatellite;
-        boolean mRequiresCell;
-        boolean mHasMonetaryCost;
-        boolean mSupportsAltitude;
-        boolean mSupportsSpeed;
-        boolean mSupportsBearing;
-        int mPowerRequirement;
-        int mAccuracy;
-
-        public MockProvider(String name,  boolean requiresNetwork, boolean requiresSatellite,
-            boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
-            boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
-            super(name);
-
-            mRequiresNetwork = requiresNetwork;
-            mRequiresSatellite = requiresSatellite;
-            mRequiresCell = requiresCell;
-            mHasMonetaryCost = hasMonetaryCost;
-            mSupportsAltitude = supportsAltitude;
-            mSupportsBearing = supportsBearing;
-            mSupportsSpeed = supportsSpeed;
-            mPowerRequirement = powerRequirement;
-            mAccuracy = accuracy;
-        }
-
-        @Override
-        public void disable() {
-            String name = getName();
-            // We shouldn't normally need to lock, since this should only be called
-            // by the service with the lock held, but let's be paranid.
-            synchronized (mLocationListeners) {
-                mEnabledProviders.remove(name);
-                mDisabledProviders.add(name);
-            }
-        }
-
-        @Override
-        public void enable() {
-            String name = getName();
-            // We shouldn't normally need to lock, since this should only be called
-            // by the service with the lock held, but let's be paranid.
-            synchronized (mLocationListeners) {
-                mEnabledProviders.add(name);
-                mDisabledProviders.remove(name);
-            }
-        }
-
-        @Override
-        public boolean getLocation(Location l) {
-            // We shouldn't normally need to lock, since this should only be called
-            // by the service with the lock held, but let's be paranid.
-            synchronized (mLocationListeners) {
-                Location loc = mMockProviderLocation.get(getName());
-                if (loc == null) {
-                    return false;
-                }
-                l.set(loc);
-                return true;
-            }
-        }
-
-        @Override
-        public int getStatus(Bundle extras) {
-            // We shouldn't normally need to lock, since this should only be called
-            // by the service with the lock held, but let's be paranid.
-            synchronized (mLocationListeners) {
-                String name = getName();
-                Integer s = mMockProviderStatus.get(name);
-                int status = (s == null) ? AVAILABLE : s.intValue();
-                Bundle newExtras = mMockProviderStatusExtras.get(name);
-                if (newExtras != null) {
-                    extras.clear();
-                    extras.putAll(newExtras);
-                }
-                return status;
-            }
-        }
-
-        @Override
-        public boolean isEnabled() {
-            // We shouldn't normally need to lock, since this should only be called
-            // by the service with the lock held, but let's be paranid.
-            synchronized (mLocationListeners) {
-                return mEnabledProviders.contains(getName());
-            }
-        }
-
-        @Override
-        public int getAccuracy() {
-            return mAccuracy;
-        }
-
-        @Override
-        public int getPowerRequirement() {
-            return mPowerRequirement;
-        }
-
-        @Override
-        public boolean hasMonetaryCost() {
-            return mHasMonetaryCost;
-        }
-
-        @Override
-        public boolean requiresCell() {
-            return mRequiresCell;
-        }
-
-        @Override
-        public boolean requiresNetwork() {
-            return mRequiresNetwork;
-        }
-
-        @Override
-        public boolean requiresSatellite() {
-            return mRequiresSatellite;
-        }
-
-        @Override
-        public boolean supportsAltitude() {
-            return mSupportsAltitude;
-        }
-
-        @Override
-        public boolean supportsBearing() {
-            return mSupportsBearing;
-        }
-
-        @Override
-        public boolean supportsSpeed() {
-            return mSupportsSpeed;
-        }
-    }
-    
     private void checkMockPermissionsSafe() {
         boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
@@ -2516,60 +1925,68 @@
         boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
         checkMockPermissionsSafe();
 
-        synchronized (mLocationListeners) {
-            MockProvider provider = new MockProvider(name, requiresNetwork, requiresSatellite,
+        synchronized (mLock) {
+            MockProvider provider = new MockProvider(name, this,
+                requiresNetwork, requiresSatellite,
                 requiresCell, hasMonetaryCost, supportsAltitude,
                 supportsSpeed, supportsBearing, powerRequirement, accuracy);
             if (LocationProviderImpl.getProvider(name) != null) {
                 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
             }
             LocationProviderImpl.addProvider(provider);
+            mMockProviders.put(name, provider);
             updateProvidersLocked();
         }
     }
 
     public void removeTestProvider(String provider) {
         checkMockPermissionsSafe();
-        synchronized (mLocationListeners) {
-            LocationProviderImpl p = LocationProviderImpl.getProvider(provider);
-            if (p == null) {
+        synchronized (mLock) {
+            MockProvider mockProvider = mMockProviders.get(provider);
+            if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
-            LocationProviderImpl.removeProvider(p);
+            LocationProviderImpl.removeProvider(mockProvider);
+            mMockProviders.remove(mockProvider);
             updateProvidersLocked();
         }
     }
 
     public void setTestProviderLocation(String provider, Location loc) {
         checkMockPermissionsSafe();
-        synchronized (mLocationListeners) {
-            if (LocationProviderImpl.getProvider(provider) == null) {
+        synchronized (mLock) {
+            MockProvider mockProvider = mMockProviders.get(provider);
+            if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
-            mMockProviderLocation.put(provider, loc);
+            mockProvider.setLocation(loc);
         }
     }
 
     public void clearTestProviderLocation(String provider) {
         checkMockPermissionsSafe();
-        synchronized (mLocationListeners) {
-            if (LocationProviderImpl.getProvider(provider) == null) {
+        synchronized (mLock) {
+            MockProvider mockProvider = mMockProviders.get(provider);
+            if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
-            mMockProviderLocation.remove(provider);
+            mockProvider.clearLocation();
         }
     }
 
     public void setTestProviderEnabled(String provider, boolean enabled) {
         checkMockPermissionsSafe();
-        synchronized (mLocationListeners) {
-            if (LocationProviderImpl.getProvider(provider) == null) {
+        synchronized (mLock) {
+            MockProvider mockProvider = mMockProviders.get(provider);
+            if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
             if (enabled) {
+                mockProvider.enable();
                 mEnabledProviders.add(provider);
                 mDisabledProviders.remove(provider);
             } else {
+                mockProvider.disable();
                 mEnabledProviders.remove(provider);
                 mDisabledProviders.add(provider);
             }
@@ -2579,8 +1996,9 @@
 
     public void clearTestProviderEnabled(String provider) {
         checkMockPermissionsSafe();
-        synchronized (mLocationListeners) {
-            if (LocationProviderImpl.getProvider(provider) == null) {
+        synchronized (mLock) {
+            MockProvider mockProvider = mMockProviders.get(provider);
+            if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
             mEnabledProviders.remove(provider);
@@ -2591,25 +2009,23 @@
 
     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
         checkMockPermissionsSafe();
-        synchronized (mLocationListeners) {
-            if (LocationProviderImpl.getProvider(provider) == null) {
+        synchronized (mLock) {
+            MockProvider mockProvider = mMockProviders.get(provider);
+            if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
-            mMockProviderStatus.put(provider, new Integer(status));
-            mMockProviderStatusExtras.put(provider, extras);
-            mMockProviderStatusUpdateTime.put(provider, new Long(updateTime));
+            mockProvider.setStatus(status, extras, updateTime);
         }
     }
 
     public void clearTestProviderStatus(String provider) {
         checkMockPermissionsSafe();
-        synchronized (mLocationListeners) {
-            if (LocationProviderImpl.getProvider(provider) == null) {
+        synchronized (mLock) {
+            MockProvider mockProvider = mMockProviders.get(provider);
+            if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
             }
-            mMockProviderStatus.remove(provider);
-            mMockProviderStatusExtras.remove(provider);
-            mMockProviderStatusUpdateTime.remove(provider);
+            mockProvider.clearStatus();
         }
     }
 
@@ -2628,57 +2044,29 @@
             return;
         }
         
-        synchronized (mLocationListeners) {
+        synchronized (mLock) {
             pw.println("Current Location Manager state:");
             pw.println("  sProvidersLoaded=" + sProvidersLoaded);
             pw.println("  mGpsLocationProvider=" + mGpsLocationProvider);
-            pw.println("  mGpsNavigating=" + mGpsNavigating);
             pw.println("  mNetworkLocationProvider=" + mNetworkLocationProvider);
-            pw.println("  mNetworkLocationInterface=" + mNetworkLocationInterface);
-            pw.println("  mLastSignalStrength=" + mLastSignalStrength
-                    + "  mLastRadioType=" + mLastRadioType);
-            pw.println("  mCellLocationUpdater=" + mCellLocationUpdater);
-            pw.println("  mLastCellState=" + mLastCellState);
             pw.println("  mCollector=" + mCollector);
             pw.println("  mAlarmInterval=" + mAlarmInterval
-                    + " mScreenOn=" + mScreenOn
                     + " mWakeLockAcquireTime=" + mWakeLockAcquireTime);
             pw.println("  mWakeLockGpsReceived=" + mWakeLockGpsReceived
                     + " mWakeLockNetworkReceived=" + mWakeLockNetworkReceived);
-            pw.println("  mWifiWakeLockAcquired=" + mWifiWakeLockAcquired
-                    + " mCellWakeLockAcquired=" + mCellWakeLockAcquired);
             pw.println("  Listeners:");
-            int N = mListeners.size();
+            int N = mReceivers.size();
             for (int i=0; i<N; i++) {
-                pw.println("    " + mListeners.get(i));
+                pw.println("    " + mReceivers.get(i));
             }
             pw.println("  Location Listeners:");
-            for (Map.Entry<Receiver, HashMap<String,UpdateRecord>> i
-                    : mLocationListeners.entrySet()) {
-                pw.println("    " + i.getKey() + ":");
-                for (Map.Entry<String,UpdateRecord> j : i.getValue().entrySet()) {
+            for (Receiver i : mReceivers.values()) {
+                pw.println("    " + i + ":");
+                for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) {
                     pw.println("      " + j.getKey() + ":");
                     j.getValue().dump(pw, "        ");
                 }
             }
-            pw.println("  Last Fix Broadcasts:");
-            for (Map.Entry<Receiver, HashMap<String,Location>> i
-                    : mLastFixBroadcast.entrySet()) {
-                pw.println("    " + i.getKey() + ":");
-                for (Map.Entry<String,Location> j : i.getValue().entrySet()) {
-                    pw.println("      " + j.getKey() + ":");
-                    j.getValue().dump(new PrintWriterPrinter(pw), "        ");
-                }
-            }
-            pw.println("  Last Status Broadcasts:");
-            for (Map.Entry<Receiver, HashMap<String,Long>> i
-                    : mLastStatusBroadcast.entrySet()) {
-                pw.println("    " + i.getKey() + ":");
-                for (Map.Entry<String,Long> j : i.getValue().entrySet()) {
-                    pw.println("      " + j.getKey() + " -> 0x"
-                            + Long.toHexString(j.getValue()));
-                }
-            }
             pw.println("  Records by Provider:");
             for (Map.Entry<String, ArrayList<UpdateRecord>> i
                     : mRecordsByProvider.entrySet()) {
@@ -2688,12 +2076,6 @@
                     j.dump(pw, "        ");
                 }
             }
-            pw.println("  Locations by Provider:");
-            for (Map.Entry<String, Location> i
-                    : mLocationsByProvider.entrySet()) {
-                pw.println("    " + i.getKey() + ":");
-                i.getValue().dump(new PrintWriterPrinter(pw), "      ");
-            }
             pw.println("  Last Known Locations:");
             for (Map.Entry<String, Location> i
                     : mLastKnownLocation.entrySet()) {
@@ -2715,6 +2097,7 @@
                     i.dump(pw, "      ");
                 }
             }
+            pw.println("  mProximityReceiver=" + mProximityReceiver);
             pw.println("  mProximityListener=" + mProximityListener);
             if (mEnabledProviders.size() > 0) {
                 pw.println("  Enabled Providers:");
@@ -2733,42 +2116,9 @@
             if (mMockProviders.size() > 0) {
                 pw.println("  Mock Providers:");
                 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
-                    pw.println("    " + i.getKey() + " -> " + i.getValue());
+                    i.getValue().dump(pw, "      ");
                 }
             }
-            if (mMockProviderLocation.size() > 0) {
-                pw.println("  Mock Provider Location:");
-                for (Map.Entry<String, Location> i : mMockProviderLocation.entrySet()) {
-                    pw.println("    " + i.getKey() + ":");
-                    i.getValue().dump(new PrintWriterPrinter(pw), "      ");
-                }
-            }
-            if (mMockProviderStatus.size() > 0) {
-                pw.println("  Mock Provider Status:");
-                for (Map.Entry<String, Integer> i : mMockProviderStatus.entrySet()) {
-                    pw.println("    " + i.getKey() + " -> 0x"
-                            + Integer.toHexString(i.getValue()));
-                }
-            }
-            if (mMockProviderStatusExtras.size() > 0) {
-                pw.println("  Mock Provider Status Extras:");
-                for (Map.Entry<String, Bundle> i : mMockProviderStatusExtras.entrySet()) {
-                    pw.println("    " + i.getKey() + " -> " + i.getValue());
-                }
-            }
-            if (mMockProviderStatusUpdateTime.size() > 0) {
-                pw.println("  Mock Provider Status Update Time:");
-                for (Map.Entry<String, Long> i : mMockProviderStatusUpdateTime.entrySet()) {
-                    pw.println("    " + i.getKey() + " -> " + i.getValue());
-                }
-            }
-            pw.println("  Reported GPS UIDs @ seq " + mReportedGpsSeq + ":");
-            N = mReportedGpsUids.size();
-            for (int i=0; i<N; i++)  {
-                pw.println("    UID " + mReportedGpsUids.keyAt(i)
-                        + " seq=" + mReportedGpsUids.valueAt(i));
-            }
         }
     }
 }
-
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 9e062f4..159bc76 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2932,11 +2932,12 @@
         }
 
         @Override
-        protected void dumpFilter(Printer out, String prefix,
+        protected void dumpFilter(PrintWriter out, String prefix,
                 PackageParser.ActivityIntentInfo filter) {
-            out.println(prefix
-                    + Integer.toHexString(System.identityHashCode(filter.activity))
-                    + " " + filter.activity.component.flattenToShortString());
+            out.print(prefix); out.print(
+                    Integer.toHexString(System.identityHashCode(filter.activity)));
+                    out.print(' ');
+                    out.println(filter.activity.componentShortName);
         }
 
 //        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
@@ -3064,11 +3065,12 @@
         }
 
         @Override
-        protected void dumpFilter(Printer out, String prefix,
+        protected void dumpFilter(PrintWriter out, String prefix,
                 PackageParser.ServiceIntentInfo filter) {
-            out.println(prefix
-                    + Integer.toHexString(System.identityHashCode(filter.service))
-                    + " " + filter.service.component.flattenToShortString());
+            out.print(prefix); out.print(
+                    Integer.toHexString(System.identityHashCode(filter.service)));
+                    out.print(' ');
+                    out.println(filter.service.componentShortName);
         }
 
 //        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
@@ -4578,80 +4580,83 @@
             return;
         }
 
-        Printer printer = new PrintWriterPrinter(pw);
         synchronized (mPackages) {
             pw.println("Activity Resolver Table:");
-            mActivities.dump(printer, "  ");
+            mActivities.dump(pw, "  ");
             pw.println(" ");
             pw.println("Receiver Resolver Table:");
-            mReceivers.dump(printer, "  ");
+            mReceivers.dump(pw, "  ");
             pw.println(" ");
             pw.println("Service Resolver Table:");
-            mServices.dump(printer, "  ");
+            mServices.dump(pw, "  ");
             pw.println(" ");
             pw.println("Preferred Activities:");
-            mSettings.mPreferredActivities.dump(printer, "  ");
+            mSettings.mPreferredActivities.dump(pw, "  ");
             pw.println(" ");
             pw.println("Preferred Packages:");
             {
                 for (PackageSetting ps : mSettings.mPreferredPackages) {
-                    pw.println("  " + ps.name);
+                    pw.print("  "); pw.println(ps.name);
                 }
             }
             pw.println(" ");
             pw.println("Permissions:");
             {
                 for (BasePermission p : mSettings.mPermissions.values()) {
-                    pw.println("  Permission [" + p.name + "] ("
-                            + Integer.toHexString(System.identityHashCode(p))
-                            + "):");
-                    pw.println("    sourcePackage=" + p.sourcePackage);
-                    pw.println("    uid=" + p.uid
-                            + " gids=" + arrayToString(p.gids)
-                            + " type=" + p.type);
+                    pw.print("  Permission ["); pw.print(p.name); pw.print("] (");
+                            pw.print(Integer.toHexString(System.identityHashCode(p)));
+                            pw.println("):");
+                    pw.print("    sourcePackage="); pw.println(p.sourcePackage);
+                    pw.print("    uid="); pw.print(p.uid);
+                            pw.print(" gids="); pw.print(arrayToString(p.gids));
+                            pw.print(" type="); pw.println(p.type);
                 }
             }
             pw.println(" ");
             pw.println("Packages:");
             {
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    pw.println("  Package [" + ps.name + "] ("
-                            + Integer.toHexString(System.identityHashCode(ps))
-                            + "):");
-                    pw.println("    userId=" + ps.userId
-                            + " gids=" + arrayToString(ps.gids));
-                    pw.println("    sharedUser=" + ps.sharedUser);
-                    pw.println("    pkg=" + ps.pkg);
-                    pw.println("    codePath=" + ps.codePathString);
-                    pw.println("    resourcePath=" + ps.resourcePathString);
+                    pw.print("  Package ["); pw.print(ps.name); pw.print("] (");
+                            pw.print(Integer.toHexString(System.identityHashCode(ps)));
+                            pw.println("):");
+                    pw.print("    userId="); pw.print(ps.userId);
+                            pw.print(" gids="); pw.println(arrayToString(ps.gids));
+                    pw.print("    sharedUser="); pw.println(ps.sharedUser);
+                    pw.print("    pkg="); pw.println(ps.pkg);
+                    pw.print("    codePath="); pw.println(ps.codePathString);
+                    pw.print("    resourcePath="); pw.println(ps.resourcePathString);
                     if (ps.pkg != null) {
-                        pw.println("    dataDir=" + ps.pkg.applicationInfo.dataDir);
+                        pw.print("    dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
                     }
-                    pw.println("    timeStamp=" + ps.getTimeStampStr());
-                    pw.println("    signatures=" + ps.signatures);
-                    pw.println("    permissionsFixed=" + ps.permissionsFixed
-                            + " pkgFlags=0x" + Integer.toHexString(ps.pkgFlags)
-                            + " installStatus=" + ps.installStatus
-                            + " enabled=" + ps.enabled);
+                    pw.print("    timeStamp="); pw.println(ps.getTimeStampStr());
+                    pw.print("    signatures="); pw.println(ps.signatures);
+                    pw.print("    permissionsFixed="); pw.print(ps.permissionsFixed);
+                            pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
+                            pw.print(" installStatus="); pw.print(ps.installStatus);
+                            pw.print(" enabled="); pw.println(ps.enabled);
                     if (ps.disabledComponents.size() > 0) {
                         pw.println("    disabledComponents:");
                         for (String s : ps.disabledComponents) {
-                            pw.println("      " + s);
+                            pw.print("      "); pw.println(s);
                         }
                     }
                     if (ps.enabledComponents.size() > 0) {
                         pw.println("    enabledComponents:");
                         for (String s : ps.enabledComponents) {
-                            pw.println("      " + s);
+                            pw.print("      "); pw.println(s);
                         }
                     }
-                    pw.println("    grantedPermissions:");
-                    for (String s : ps.grantedPermissions) {
-                        pw.println("      " + s);
+                    if (ps.grantedPermissions.size() > 0) {
+                        pw.println("    grantedPermissions:");
+                        for (String s : ps.grantedPermissions) {
+                            pw.print("      "); pw.println(s);
+                        }
                     }
-                    pw.println("    loadedPermissions:");
-                    for (String s : ps.loadedPermissions) {
-                        pw.println("      " + s);
+                    if (ps.loadedPermissions.size() > 0) {
+                        pw.println("    loadedPermissions:");
+                        for (String s : ps.loadedPermissions) {
+                            pw.print("      "); pw.println(s);
+                        }
                     }
                 }
             }
@@ -4659,18 +4664,18 @@
             pw.println("Shared Users:");
             {
                 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
-                    pw.println("  SharedUser [" + su.name + "] ("
-                            + Integer.toHexString(System.identityHashCode(su))
-                            + "):");
-                    pw.println("    userId=" + su.userId
-                            + " gids=" + arrayToString(su.gids));
+                    pw.print("  SharedUser ["); pw.print(su.name); pw.print("] (");
+                            pw.print(Integer.toHexString(System.identityHashCode(su)));
+                            pw.println("):");
+                    pw.print("    userId="); pw.print(su.userId);
+                            pw.print(" gids="); pw.println(arrayToString(su.gids));
                     pw.println("    grantedPermissions:");
                     for (String s : su.grantedPermissions) {
-                        pw.println("      " + s);
+                        pw.print("      "); pw.println(s);
                     }
                     pw.println("    loadedPermissions:");
                     for (String s : su.loadedPermissions) {
-                        pw.println("      " + s);
+                        pw.print("      "); pw.println(s);
                     }
                 }
             }
@@ -5302,16 +5307,19 @@
         private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
                     new IntentResolver<PreferredActivity, PreferredActivity>() {
             @Override
-            protected void dumpFilter(Printer out, String prefix,
+            protected void dumpFilter(PrintWriter out, String prefix,
                     PreferredActivity filter) {
-                out.println(prefix
-                        + Integer.toHexString(System.identityHashCode(filter))
-                        + " " + filter.mActivity.flattenToShortString()
-                        + " match=0x" + Integer.toHexString(filter.mMatch));
+                out.print(prefix); out.print(
+                        Integer.toHexString(System.identityHashCode(filter)));
+                        out.print(' ');
+                        out.print(filter.mActivity.flattenToShortString());
+                        out.print(" match=0x");
+                        out.println( Integer.toHexString(filter.mMatch));
                 if (filter.mSetComponents != null) {
-                    out.println(prefix + "  Selected from:");
+                    out.print(prefix); out.println("  Selected from:");
                     for (int i=0; i<filter.mSetComponents.length; i++) {
-                        out.println(prefix + "    " + filter.mSetComponents[i]);
+                        out.print(prefix); out.print("    ");
+                                out.println(filter.mSetComponents[i]);
                     }
                 }
             }
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 54e77f0..8850c31 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -165,7 +165,6 @@
      * Character buffer used to parse scan results (optimization)
      */
     private static final int SCAN_RESULT_BUFFER_SIZE = 512;
-    private char[] mScanResultBuffer;
     private boolean mNeedReconfig;
 
     /*
@@ -204,8 +203,6 @@
                 }
             };
 
-        mScanResultBuffer = new char [SCAN_RESULT_BUFFER_SIZE];
-
         HandlerThread wifiThread = new HandlerThread("WifiService");
         wifiThread.start();
         mWifiHandler = new WifiHandler(wifiThread.getLooper());
@@ -1217,61 +1214,13 @@
                     lineBeg = lineEnd + 1;
                     continue;
                 }
-                int lineLen = lineEnd - lineBeg;
-                if (0 < lineLen && lineLen <= SCAN_RESULT_BUFFER_SIZE) {
-                    int scanResultLevel = 0;
-                    /*
-                     * At most one thread should have access to the buffer at a time!
-                     */
-                    synchronized(mScanResultBuffer) {
-                        boolean parsingScanResultLevel = false;
-                        for (int i = lineBeg; i < lineEnd; ++i) {
-                            char ch = reply.charAt(i);
-                            /*
-                             * Assume that the signal level starts with a '-'
-                             */
-                            if (ch == '-') {
-                                /*
-                                 * Skip whatever instances of '-' we may have
-                                 * after we parse the signal level
-                                 */
-                                parsingScanResultLevel = (scanResultLevel == 0);
-                            } else if (parsingScanResultLevel) {
-                                int digit = Character.digit(ch, 10);
-                                if (0 <= digit) {
-                                    scanResultLevel =
-                                        10 * scanResultLevel + digit;
-                                    /*
-                                     * Replace the signal level number in
-                                     * the string with 0's for caching
-                                     */
-                                    ch = '0';
-                                } else {
-                                    /*
-                                     * Reset the flag if we meet a non-digit
-                                     * character
-                                     */
-                                    parsingScanResultLevel = false;
-                                }
-                            }
-                            mScanResultBuffer[i - lineBeg] = ch;
-                        }
-                        if (scanResultLevel != 0) {
-                            ScanResult scanResult = parseScanResult(
-                                new String(mScanResultBuffer, 0, lineLen));
-                            if (scanResult != null) {
-                              scanResult.level = -scanResultLevel;
-                              scanList.add(scanResult);
-                            }
-                        } else if (DBG) {
-                            Log.w(TAG,
-                                  "ScanResult.level=0: misformatted scan result?");
-                        }
-                    }
-                } else if (0 < lineLen) {
-                    if (DBG) {
-                        Log.w(TAG, "Scan result line is too long: " +
-                              (lineEnd - lineBeg) + ", skipping the line!");
+                if (lineEnd > lineBeg) {
+                    String line = reply.substring(lineBeg, lineEnd);
+                    ScanResult scanResult = parseScanResult(line);
+                    if (scanResult != null) {
+                        scanList.add(scanResult);
+                    } else if (DBG) {
+                        Log.w(TAG, "misformatted scan result for: " + line);
                     }
                 }
                 lineBeg = lineEnd + 1;
@@ -1294,21 +1243,29 @@
              * must synchronized here!
              */
             synchronized (mScanResultCache) {
-                scanResult = mScanResultCache.get(line);
-                if (scanResult == null) {
-                    String[] result = scanResultPattern.split(line);
-                    if (3 <= result.length && result.length <= 5) {
-                        // bssid | frequency | level | flags | ssid
-                        int frequency;
-                        int level;
-                        try {
-                            frequency = Integer.parseInt(result[1]);
-                            level = Integer.parseInt(result[2]);
-                        } catch (NumberFormatException e) {
-                            frequency = 0;
-                            level = 0;
-                        }
+                String[] result = scanResultPattern.split(line);
+                if (3 <= result.length && result.length <= 5) {
+                    String bssid = result[0];
+                    // bssid | frequency | level | flags | ssid
+                    int frequency;
+                    int level;
+                    try {
+                        frequency = Integer.parseInt(result[1]);
+                        level = Integer.parseInt(result[2]);
+                        /* some implementations avoid negative values by adding 256
+                         * so we need to adjust for that here.
+                         */
+                        if (level > 0) level -= 256;
+                    } catch (NumberFormatException e) {
+                        frequency = 0;
+                        level = 0;
+                    }
 
+                    // bssid is the hash key
+                    scanResult = mScanResultCache.get(bssid);
+                    if (scanResult != null) {
+                        scanResult.level = level;
+                    } else {
                         /*
                          * The formatting of the results returned by
                          * wpa_supplicant is intended to make the fields
@@ -1341,13 +1298,13 @@
                         if (0 < ssid.trim().length()) {
                             scanResult =
                                 new ScanResult(
-                                    ssid, result[0], flags, level, frequency);
-                            mScanResultCache.put(line, scanResult);
+                                    ssid, bssid, flags, level, frequency);
+                            mScanResultCache.put(bssid, scanResult);
                         }
-                    } else {
-                        Log.w(TAG, "Misformatted scan result text with " +
-                              result.length + " fields: " + line);
                     }
+                } else {
+                    Log.w(TAG, "Misformatted scan result text with " +
+                          result.length + " fields: " + line);
                 }
             }
         }
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index fe97b93..9443a95 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -75,14 +75,6 @@
     private static final boolean V = false || Config.LOGV;
     private static final boolean D = true || Config.LOGD;
     
-    /*
-     * When this was "net.dns1", sometimes the mobile data's DNS was seen
-     * instead due to a race condition. All we really care about is the
-     * DHCP-replied DNS server anyway.
-     */
-    /** The system property whose value provides the current DNS address. */
-    private static final String SYSTEMPROPERTY_KEY_DNS = "dhcp.tiwlan0.dns1";
-
     private Context mContext;
     private ContentResolver mContentResolver;
     private WifiStateTracker mWifiStateTracker;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 0b1ddc8..321b17e 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -77,7 +77,6 @@
 import android.os.SystemProperties;
 import android.os.TokenWatcher;
 import android.provider.Settings;
-import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseIntArray;
@@ -137,7 +136,7 @@
     
     static final boolean PROFILE_ORIENTATION = false;
     static final boolean BLUR = true;
-    static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean localLOGV = DEBUG;
     
     static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
     
@@ -2023,7 +2022,7 @@
             wtoken.appFullscreen = fullscreen;
             wtoken.requestedOrientation = requestedOrientation;
             mAppTokens.add(addPos, wtoken);
-            if (Config.LOGV) Log.v(TAG, "Adding new app token: " + wtoken);
+            if (localLOGV) Log.v(TAG, "Adding new app token: " + wtoken);
             mTokenMap.put(token.asBinder(), wtoken);
             mTokenList.add(wtoken);
             
@@ -4801,14 +4800,11 @@
                     mPaused = true;
                 } else {
                     if (mLastWin == null) {
-                        if (Config.LOGI) Log.i(
-                            TAG, "Key dispatching not paused: no last window.");
+                        Log.i(TAG, "Key dispatching not paused: no last window.");
                     } else if (mFinished) {
-                        if (Config.LOGI) Log.i(
-                            TAG, "Key dispatching not paused: finished last key.");
+                        Log.i(TAG, "Key dispatching not paused: finished last key.");
                     } else {
-                        if (Config.LOGI) Log.i(
-                            TAG, "Key dispatching not paused: window in higher layer.");
+                        Log.i(TAG, "Key dispatching not paused: window in higher layer.");
                     }
                 }
                 */
@@ -5179,6 +5175,7 @@
         final IInputContext mInputContext;
         final int mUid;
         final int mPid;
+        final String mStringName;
         SurfaceSession mSurfaceSession;
         int mNumWindow = 0;
         boolean mClientDead = false;
@@ -5202,6 +5199,14 @@
             mInputContext = inputContext;
             mUid = Binder.getCallingUid();
             mPid = Binder.getCallingPid();
+            StringBuilder sb = new StringBuilder();
+            sb.append("Session{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(" uid ");
+            sb.append(mUid);
+            sb.append("}");
+            mStringName = sb.toString();
+            
             synchronized (mWindowMap) {
                 if (mInputMethodManager == null && mHaveInputMethods) {
                     IBinder b = ServiceManager.getService(
@@ -5381,20 +5386,24 @@
         }
         
         void dump(PrintWriter pw, String prefix) {
-            pw.println(prefix + this);
-            pw.println(prefix + "mNumWindow=" + mNumWindow
-                    + " mClientDead=" + mClientDead
-                    + " mSurfaceSession=" + mSurfaceSession);
-            pw.println(prefix + "mPendingPointerWindow=" + mPendingPointerWindow
-                    + " mPendingPointerMove=" + mPendingPointerMove);
-            pw.println(prefix + "mPendingTrackballWindow=" + mPendingTrackballWindow
-                    + " mPendingTrackballMove=" + mPendingTrackballMove);
+            pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
+                    pw.print(" mClientDead="); pw.print(mClientDead);
+                    pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
+            if (mPendingPointerWindow != null || mPendingPointerMove != null) {
+                pw.print(prefix);
+                        pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
+                        pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
+            }
+            if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
+                pw.print(prefix);
+                        pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
+                        pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
+            }
         }
 
         @Override
         public String toString() {
-            return "Session{"
-                + Integer.toHexString(System.identityHashCode(this)) + "}";
+            return mStringName;
         }
     }
 
@@ -6462,67 +6471,114 @@
         }
 
         void dump(PrintWriter pw, String prefix) {
-            pw.println(prefix + this);
-            pw.println(prefix + "mSession=" + mSession
-                  + " mClient=" + mClient.asBinder());
-            pw.println(prefix + "mAttrs=" + mAttrs);
-            pw.println(prefix + "mAttachedWindow=" + mAttachedWindow
-                    + " mLayoutAttached=" + mLayoutAttached
-                    + " mIsImWindow=" + mIsImWindow);
-            pw.println(prefix + "mBaseLayer=" + mBaseLayer
-                  + " mSubLayer=" + mSubLayer
-                  + " mAnimLayer=" + mLayer + "+"
-                  + (mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
-                          : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))
-                  + "=" + mAnimLayer
-                  + " mLastLayer=" + mLastLayer);
-            pw.println(prefix + "mSurface=" + mSurface);
-            pw.println(prefix + "mToken=" + mToken);
-            pw.println(prefix + "mRootToken=" + mRootToken);
-            pw.println(prefix + "mAppToken=" + mAppToken);
-            pw.println(prefix + "mTargetAppToken=" + mTargetAppToken);
-            pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility)
-                  + " mPolicyVisibility=" + mPolicyVisibility
-                  + " (after=" + mPolicyVisibilityAfterAnim
-                  + ") mAttachedHidden=" + mAttachedHidden
-                  + " mLastHidden=" + mLastHidden
-                  + " mHaveFrame=" + mHaveFrame);
-            pw.println(prefix + "Requested w=" + mRequestedWidth + " h=" + mRequestedHeight
-                  + " x=" + mReqXPos + " y=" + mReqYPos);
-            pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString()
-                    + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString()
-                    + " mTouchableInsets=" + mTouchableInsets
-                    + " pending=" + mGivenInsetsPending);
-            pw.println(prefix + "mShownFrame=" + mShownFrame.toShortString()
-                  + " last=" + mLastShownFrame.toShortString());
-            pw.println(prefix + "mFrame=" + mFrame.toShortString()
-                    + " last=" + mLastFrame.toShortString());
-            pw.println(prefix + "mContainingFrame=" + mContainingFrame.toShortString()
-                    + " mDisplayFrame=" + mDisplayFrame.toShortString());
-            pw.println(prefix + "mContentFrame=" + mContentFrame.toShortString()
-                    + " mVisibleFrame=" + mVisibleFrame.toShortString());
-            pw.println(prefix + "mContentInsets=" + mContentInsets.toShortString()
-                    + " last=" + mLastContentInsets.toShortString()
-                    + " mVisibleInsets=" + mVisibleInsets.toShortString()
-                    + " last=" + mLastVisibleInsets.toShortString());
-            pw.println(prefix + "mShownAlpha=" + mShownAlpha
-                  + " mAlpha=" + mAlpha + " mLastAlpha=" + mLastAlpha);
-            pw.println(prefix + "mAnimating=" + mAnimating
-                    + " mLocalAnimating=" + mLocalAnimating
-                    + " mAnimationIsEntrance=" + mAnimationIsEntrance
-                    + " mAnimation=" + mAnimation);
-            pw.println(prefix + "XForm: has=" + mHasTransformation
-                    + " " + mTransformation.toShortString());
-            pw.println(prefix + "mDrawPending=" + mDrawPending
-                  + " mCommitDrawPending=" + mCommitDrawPending
-                  + " mReadyToShow=" + mReadyToShow
-                  + " mHasDrawn=" + mHasDrawn);
-            pw.println(prefix + "mExiting=" + mExiting
-                    + " mRemoveOnExit=" + mRemoveOnExit
-                    + " mDestroying=" + mDestroying
-                    + " mRemoved=" + mRemoved);
-            pw.println(prefix + "mOrientationChanging=" + mOrientationChanging
-                    + " mAppFreezing=" + mAppFreezing);
+            StringBuilder sb = new StringBuilder(64);
+            
+            pw.print(prefix); pw.print("mSession="); pw.print(mSession);
+                    pw.print(" mClient="); pw.println(mClient.asBinder());
+            pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
+            if (mAttachedWindow != null || mLayoutAttached) {
+                pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
+                        pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
+            }
+            if (mIsImWindow) {
+                pw.print(prefix); pw.print("mIsImWindow="); pw.println(mIsImWindow);
+            }
+            pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
+                    pw.print(" mSubLayer="); pw.print(mSubLayer);
+                    pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
+                    pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
+                          : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
+                    pw.print("="); pw.print(mAnimLayer);
+                    pw.print(" mLastLayer="); pw.println(mLastLayer);
+            if (mSurface != null) {
+                pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+            }
+            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
+            pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
+            if (mAppToken != null) {
+                pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+            }
+            if (mTargetAppToken != null) {
+                pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
+            }
+            pw.print(prefix); pw.print("mViewVisibility=0x");
+                    pw.print(Integer.toHexString(mViewVisibility));
+                    pw.print(" mLastHidden="); pw.print(mLastHidden);
+                    pw.print(" mHaveFrame="); pw.println(mHaveFrame);
+            if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
+                pw.print(prefix); pw.print("mPolicyVisibility=");
+                        pw.print(mPolicyVisibility);
+                        pw.print(" mPolicyVisibilityAfterAnim=");
+                        pw.print(mPolicyVisibilityAfterAnim);
+                        pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
+            }
+            pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
+                    pw.print(" h="); pw.print(mRequestedHeight);
+                    pw.print(" x="); pw.print(mReqXPos);
+                    pw.print(" y="); pw.println(mReqYPos);
+            pw.print(prefix); pw.print("mGivenContentInsets=");
+                    mGivenContentInsets.printShortString(pw);
+                    pw.print(" mGivenVisibleInsets=");
+                    mGivenVisibleInsets.printShortString(pw);
+                    pw.println();
+            if (mTouchableInsets != 0 || mGivenInsetsPending) {
+                pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
+                        pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+            }
+            pw.print(prefix); pw.print("mShownFrame=");
+                    mShownFrame.printShortString(pw);
+                    pw.print(" last="); mLastShownFrame.printShortString(pw);
+                    pw.println();
+            pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
+                    pw.print(" last="); mLastFrame.printShortString(pw);
+                    pw.println();
+            pw.print(prefix); pw.print("mContainingFrame=");
+                    mContainingFrame.printShortString(pw);
+                    pw.print(" mDisplayFrame=");
+                    mDisplayFrame.printShortString(pw);
+                    pw.println();
+            pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
+                    pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
+                    pw.println();
+            pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
+                    pw.print(" last="); mLastContentInsets.printShortString(pw);
+                    pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
+                    pw.print(" last="); mLastVisibleInsets.printShortString(pw);
+                    pw.println();
+            if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
+                pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
+                        pw.print(" mAlpha="); pw.print(mAlpha);
+                        pw.print(" mLastAlpha="); pw.println(mLastAlpha);
+            }
+            if (mAnimating || mLocalAnimating || mAnimationIsEntrance
+                    || mAnimation != null) {
+                pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
+                        pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
+                        pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
+                        pw.print(" mAnimation="); pw.println(mAnimation);
+            }
+            if (mHasTransformation || mHasLocalTransformation) {
+                pw.print(prefix); pw.print("XForm: has=");
+                        pw.print(mHasTransformation);
+                        pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
+                        pw.print(" "); mTransformation.printShortString(pw);
+                        pw.println();
+            }
+            pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
+                    pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
+                    pw.print(" mReadyToShow="); pw.print(mReadyToShow);
+                    pw.print(" mHasDrawn="); pw.println(mHasDrawn);
+            if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
+                pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
+                        pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
+                        pw.print(" mDestroying="); pw.print(mDestroying);
+                        pw.print(" mRemoved="); pw.println(mRemoved);
+            }
+            if (mOrientationChanging || mAppFreezing) {
+                pw.print(prefix); pw.print("mOrientationChanging=");
+                        pw.print(mOrientationChanging);
+                        pw.print(" mAppFreezing="); pw.println(mAppFreezing);
+            }
         }
 
         @Override
@@ -6548,6 +6604,9 @@
         // not be removed when all windows are removed.
         final boolean explicit;
         
+        // For printing.
+        String stringName;
+        
         // If this is an AppWindowToken, this is non-null.
         AppWindowToken appWindowToken;
         
@@ -6570,18 +6629,23 @@
         }
 
         void dump(PrintWriter pw, String prefix) {
-            pw.println(prefix + this);
-            pw.println(prefix + "token=" + token);
-            pw.println(prefix + "windows=" + windows);
-            pw.println(prefix + "windowType=" + windowType + " hidden=" + hidden
-                    + " hasVisible=" + hasVisible);
+            pw.print(prefix); pw.print("token="); pw.println(token);
+            pw.print(prefix); pw.print("windows="); pw.println(windows);
+            pw.print(prefix); pw.print("windowType="); pw.print(windowType);
+                    pw.print(" hidden="); pw.print(hidden);
+                    pw.print(" hasVisible="); pw.println(hasVisible);
         }
 
         @Override
         public String toString() {
-            return "WindowToken{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " token=" + token + "}";
+            if (stringName == null) {
+                StringBuilder sb = new StringBuilder();
+                sb.append("WindowToken{");
+                sb.append(Integer.toHexString(System.identityHashCode(this)));
+                sb.append(" token="); sb.append(token); sb.append('}');
+                stringName = sb.toString();
+            }
+            return stringName;
         }
     };
 
@@ -6869,38 +6933,66 @@
         
         void dump(PrintWriter pw, String prefix) {
             super.dump(pw, prefix);
-            pw.println(prefix + "app=" + (appToken != null));
-            pw.println(prefix + "allAppWindows=" + allAppWindows);
-            pw.println(prefix + "groupId=" + groupId
-                    + " requestedOrientation=" + requestedOrientation);
-            pw.println(prefix + "hiddenRequested=" + hiddenRequested
-                    + " clientHidden=" + clientHidden
-                    + " willBeHidden=" + willBeHidden
-                    + " reportedVisible=" + reportedVisible);
-            pw.println(prefix + "paused=" + paused
-                    + " freezingScreen=" + freezingScreen);
-            pw.println(prefix + "numInterestingWindows=" + numInterestingWindows
-                    + " numDrawnWindows=" + numDrawnWindows
-                    + " inPendingTransaction=" + inPendingTransaction
-                    + " allDrawn=" + allDrawn);
-            pw.println(prefix + "animating=" + animating
-                    + " animation=" + animation);
-            pw.println(prefix + "animLayerAdjustment=" + animLayerAdjustment
-                    + " transformation=" + transformation.toShortString());
-            pw.println(prefix + "startingData=" + startingData
-                    + " removed=" + removed
-                    + " firstWindowDrawn=" + firstWindowDrawn);
-            pw.println(prefix + "startingWindow=" + startingWindow
-                    + " startingView=" + startingView
-                    + " startingDisplayed=" + startingDisplayed
-                    + " startingMoved" + startingMoved);
+            if (appToken != null) {
+                pw.print(prefix); pw.println("app=true");
+            }
+            if (allAppWindows.size() > 0) {
+                pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
+            }
+            pw.print(prefix); pw.print("groupId="); pw.print(groupId);
+                    pw.print(" requestedOrientation="); pw.println(requestedOrientation);
+            pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
+                    pw.print(" clientHidden="); pw.print(clientHidden);
+                    pw.print(" willBeHidden="); pw.print(willBeHidden);
+                    pw.print(" reportedVisible="); pw.println(reportedVisible);
+            if (paused || freezingScreen) {
+                pw.print(prefix); pw.print("paused="); pw.print(paused);
+                        pw.print(" freezingScreen="); pw.println(freezingScreen);
+            }
+            if (numInterestingWindows != 0 || numDrawnWindows != 0
+                    || inPendingTransaction || allDrawn) {
+                pw.print(prefix); pw.print("numInterestingWindows=");
+                        pw.print(numInterestingWindows);
+                        pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
+                        pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
+                        pw.print(" allDrawn="); pw.println(allDrawn);
+            }
+            if (animating || animation != null) {
+                pw.print(prefix); pw.print("animating="); pw.print(animating);
+                        pw.print(" animation="); pw.println(animation);
+            }
+            if (animLayerAdjustment != 0) {
+                pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
+            }
+            if (hasTransformation) {
+                pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
+                        pw.print(" transformation="); transformation.printShortString(pw);
+                        pw.println();
+            }
+            if (startingData != null || removed || firstWindowDrawn) {
+                pw.print(prefix); pw.print("startingData="); pw.print(startingData);
+                        pw.print(" removed="); pw.print(removed);
+                        pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
+            }
+            if (startingWindow != null || startingView != null
+                    || startingDisplayed || startingMoved) {
+                pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
+                        pw.print(" startingView="); pw.print(startingView);
+                        pw.print(" startingDisplayed="); pw.print(startingDisplayed);
+                        pw.print(" startingMoved"); pw.println(startingMoved);
+            }
         }
 
         @Override
         public String toString() {
-            return "AppWindowToken{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " token=" + token + "}";
+            if (stringName == null) {
+                StringBuilder sb = new StringBuilder();
+                sb.append("AppWindowToken{");
+                sb.append(Integer.toHexString(System.identityHashCode(this)));
+                sb.append(" token="); sb.append(token); sb.append('}');
+                stringName = sb.toString();
+            }
+            return stringName;
         }
     }
     
@@ -7423,7 +7515,7 @@
     private boolean mInLayout = false;
     private final void performLayoutAndPlaceSurfacesLocked() {
         if (mInLayout) {
-            if (Config.DEBUG) {
+            if (DEBUG) {
                 throw new RuntimeException("Recursive call!");
             }
             Log.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
@@ -8656,7 +8748,8 @@
             pw.println("Current Window Manager state:");
             for (int i=mWindows.size()-1; i>=0; i--) {
                 WindowState w = (WindowState)mWindows.get(i);
-                pw.println("  Window #" + i + ":");
+                pw.print("  Window #"); pw.print(i); pw.print(' ');
+                        pw.print(w); pw.println(":");
                 w.dump(pw, "    ");
             }
             if (mInputMethodDialogs.size() > 0) {
@@ -8664,7 +8757,7 @@
                 pw.println("  Input method dialogs:");
                 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
                     WindowState w = mInputMethodDialogs.get(i);
-                    pw.println("  IM Dialog #" + i + ": " + w);
+                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
                 }
             }
             if (mPendingRemove.size() > 0) {
@@ -8672,7 +8765,8 @@
                 pw.println("  Remove pending for:");
                 for (int i=mPendingRemove.size()-1; i>=0; i--) {
                     WindowState w = mPendingRemove.get(i);
-                    pw.println("  Remove #" + i + ":");
+                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
+                            pw.print(w); pw.println(":");
                     w.dump(pw, "    ");
                 }
             }
@@ -8681,7 +8775,8 @@
                 pw.println("  Windows force removing:");
                 for (int i=mForceRemoves.size()-1; i>=0; i--) {
                     WindowState w = mForceRemoves.get(i);
-                    pw.println("  Removing #" + i + ":");
+                    pw.print("  Removing #"); pw.print(i); pw.print(' ');
+                            pw.print(w); pw.println(":");
                     w.dump(pw, "    ");
                 }
             }
@@ -8690,7 +8785,8 @@
                 pw.println("  Windows waiting to destroy their surface:");
                 for (int i=mDestroySurface.size()-1; i>=0; i--) {
                     WindowState w = mDestroySurface.get(i);
-                    pw.println("  Destroy #" + i + ":");
+                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
+                            pw.print(w); pw.println(":");
                     w.dump(pw, "    ");
                 }
             }
@@ -8699,7 +8795,8 @@
                 pw.println("  Windows losing focus:");
                 for (int i=mLosingFocus.size()-1; i>=0; i--) {
                     WindowState w = mLosingFocus.get(i);
-                    pw.println("  Losing #" + i + ":");
+                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
+                            pw.print(w); pw.println(":");
                     w.dump(pw, "    ");
                 }
             }
@@ -8709,7 +8806,7 @@
                 Iterator<Session> it = mSessions.iterator();
                 while (it.hasNext()) {
                     Session s = it.next();
-                    pw.println("  Session " + s);
+                    pw.print("  Session "); pw.print(s); pw.println(':');
                     s.dump(pw, "    ");
                 }
             }
@@ -8719,7 +8816,7 @@
                 Iterator<WindowToken> it = mTokenMap.values().iterator();
                 while (it.hasNext()) {
                     WindowToken token = it.next();
-                    pw.println("  Token " + token.token);
+                    pw.print("  Token "); pw.print(token.token); pw.println(':');
                     token.dump(pw, "    ");
                 }
             }
@@ -8727,14 +8824,16 @@
                 pw.println(" ");
                 pw.println("  Window token list:");
                 for (int i=0; i<mTokenList.size(); i++) {
-                    pw.println("  WindowToken #" + i + ": " + mTokenList.get(i));
+                    pw.print("  #"); pw.print(i); pw.print(": ");
+                            pw.println(mTokenList.get(i));
                 }
             }
             if (mAppTokens.size() > 0) {
                 pw.println(" ");
                 pw.println("  Application tokens in Z order:");
                 for (int i=mAppTokens.size()-1; i>=0; i--) {
-                    pw.println("  AppWindowToken #" + i + ": " + mAppTokens.get(i));
+                    pw.print("  App #"); pw.print(i); pw.print(": ");
+                            pw.println(mAppTokens.get(i));
                 }
             }
             if (mFinishedStarting.size() > 0) {
@@ -8742,7 +8841,8 @@
                 pw.println("  Finishing start of application tokens:");
                 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
                     WindowToken token = mFinishedStarting.get(i);
-                    pw.println("  Finish Starting App Token #" + i + ":");
+                    pw.print("  Finished Starting #"); pw.print(i);
+                            pw.print(' '); pw.print(token); pw.println(':');
                     token.dump(pw, "    ");
                 }
             }
@@ -8751,7 +8851,8 @@
                 pw.println("  Exiting tokens:");
                 for (int i=mExitingTokens.size()-1; i>=0; i--) {
                     WindowToken token = mExitingTokens.get(i);
-                    pw.println("  Exiting Token #" + i + ":");
+                    pw.print("  Exiting #"); pw.print(i);
+                            pw.print(' '); pw.print(token); pw.println(':');
                     token.dump(pw, "    ");
                 }
             }
@@ -8760,54 +8861,59 @@
                 pw.println("  Exiting application tokens:");
                 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
                     WindowToken token = mExitingAppTokens.get(i);
-                    pw.println("  Exiting App Token #" + i + ":");
+                    pw.print("  Exiting App #"); pw.print(i);
+                            pw.print(' '); pw.print(token); pw.println(':');
                     token.dump(pw, "    ");
                 }
             }
             pw.println(" ");
-            pw.println("  mCurrentFocus=" + mCurrentFocus);
-            pw.println("  mLastFocus=" + mLastFocus);
-            pw.println("  mFocusedApp=" + mFocusedApp);
-            pw.println("  mInputMethodTarget=" + mInputMethodTarget);
-            pw.println("  mInputMethodWindow=" + mInputMethodWindow);
-            pw.println("  mInTouchMode=" + mInTouchMode);
-            pw.println("  mSystemBooted=" + mSystemBooted
-                    + " mDisplayEnabled=" + mDisplayEnabled);
-            pw.println("  mLayoutNeeded=" + mLayoutNeeded
-                    + " mBlurShown=" + mBlurShown);
-            pw.println("  mDimShown=" + mDimShown
-                    + " current=" + mDimCurrentAlpha
-                    + " target=" + mDimTargetAlpha
-                    + " delta=" + mDimDeltaPerMs
-                    + " lastAnimTime=" + mLastDimAnimTime);
-            pw.println("  mInputMethodAnimLayerAdjustment="
-                    + mInputMethodAnimLayerAdjustment);
-            pw.println("  mDisplayFrozen=" + mDisplayFrozen
-                    + " mWindowsFreezingScreen=" + mWindowsFreezingScreen
-                    + " mAppsFreezingScreen=" + mAppsFreezingScreen);
-            pw.println("  mRotation=" + mRotation
-                    + ", mForcedAppOrientation=" + mForcedAppOrientation
-                    + ", mRequestedRotation=" + mRequestedRotation);
-            pw.println("  mAnimationPending=" + mAnimationPending
-                    + " mWindowAnimationScale=" + mWindowAnimationScale
-                    + " mTransitionWindowAnimationScale=" + mTransitionAnimationScale);
-            pw.println("  mNextAppTransition=0x"
-                    + Integer.toHexString(mNextAppTransition)
-                    + ", mAppTransitionReady=" + mAppTransitionReady
-                    + ", mAppTransitionTimeout=" + mAppTransitionTimeout);
-            pw.println("  mStartingIconInTransition=" + mStartingIconInTransition
-                    + ", mSkipAppTransitionAnimation=" + mSkipAppTransitionAnimation);
-            pw.println("  mOpeningApps=" + mOpeningApps);
-                    pw.println("  mClosingApps=" + mClosingApps);
-            pw.println("  DisplayWidth=" + mDisplay.getWidth()
-                    + " DisplayHeight=" + mDisplay.getHeight());
+            pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
+            pw.print("  mLastFocus="); pw.println(mLastFocus);
+            pw.print("  mFocusedApp="); pw.println(mFocusedApp);
+            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
+            pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
+            pw.print("  mInTouchMode="); pw.println(mInTouchMode);
+            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
+                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
+            pw.print("  mLayoutNeeded="); pw.print(mLayoutNeeded);
+                    pw.print(" mBlurShown="); pw.println(mBlurShown);
+            pw.print("  mDimShown="); pw.print(mDimShown);
+                    pw.print(" current="); pw.print(mDimCurrentAlpha);
+                    pw.print(" target="); pw.print(mDimTargetAlpha);
+                    pw.print(" delta="); pw.print(mDimDeltaPerMs);
+                    pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
+            pw.print("  mInputMethodAnimLayerAdjustment=");
+                    pw.println(mInputMethodAnimLayerAdjustment);
+            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
+                    pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
+                    pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);
+            pw.print("  mRotation="); pw.print(mRotation);
+                    pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
+                    pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
+            pw.print("  mAnimationPending="); pw.print(mAnimationPending);
+                    pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
+                    pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
+            pw.print("  mNextAppTransition=0x");
+                    pw.print(Integer.toHexString(mNextAppTransition));
+                    pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
+                    pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
+            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
+                    pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
+            if (mOpeningApps.size() > 0) {
+                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
+            }
+            if (mClosingApps.size() > 0) {
+                pw.print("  mClosingApps="); pw.println(mClosingApps);
+            }
+            pw.print("  DisplayWidth="); pw.print(mDisplay.getWidth());
+                    pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
             pw.println("  KeyWaiter state:");
-            pw.println("    mLastWin=" + mKeyWaiter.mLastWin
-                    + " mLastBinder=" + mKeyWaiter.mLastBinder);
-            pw.println("    mFinished=" + mKeyWaiter.mFinished
-                    + " mGotFirstWindow=" + mKeyWaiter.mGotFirstWindow
-                    + " mEventDispatching=" + mKeyWaiter.mEventDispatching
-                    + " mTimeToSwitch=" + mKeyWaiter.mTimeToSwitch);
+            pw.print("    mLastWin="); pw.print(mKeyWaiter.mLastWin);
+                    pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
+            pw.print("    mFinished="); pw.print(mKeyWaiter.mFinished);
+                    pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
+                    pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
+                    pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
         }
     }
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d676c00..b04f5a8 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -682,6 +682,11 @@
     HashMap<String, IBinder> mAppBindArgs;
 
     /**
+     * Temporary to avoid allocations.  Protected by main lock.
+     */
+    final StringBuilder mStringBuilder = new StringBuilder(256);
+    
+    /**
      * Used to control how we initialize the service.
      */
     boolean mStartRunning = false;
@@ -778,6 +783,8 @@
     long mLastCpuTime = 0;
     long mLastWriteTime = 0;
 
+    long mInitialStartTime = 0;
+    
     /**
      * Set to true after the system has finished booting.
      */
@@ -1270,7 +1277,7 @@
         mBatteryStatsService.getActiveStatistics().writeLocked();
         
         mUsageStatsService = new UsageStatsService( new File(
-                systemDir, "usagestats.bin").toString());
+                systemDir, "usagestats").toString());
 
         mConfiguration.makeDefault();
         mProcessStats.init();
@@ -1635,6 +1642,11 @@
         
         if (r.startTime == 0) {
             r.startTime = SystemClock.uptimeMillis();
+            if (mInitialStartTime == 0) {
+                mInitialStartTime = r.startTime;
+            }
+        } else if (mInitialStartTime == 0) {
+            mInitialStartTime = SystemClock.uptimeMillis();
         }
         
         if (app != null && app.thread != null) {
@@ -1785,7 +1797,8 @@
                 Watchdog.getInstance().processStarted(app, app.processName, pid);
             }
             
-            StringBuilder buf = new StringBuilder(128);
+            StringBuilder buf = mStringBuilder;
+            buf.setLength(0);
             buf.append("Start proc ");
             buf.append(app.processName);
             buf.append(" for ");
@@ -2813,7 +2826,6 @@
         HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
                 intent, resolvedType, aInfo, mConfiguration,
                 resultRecord, resultWho, requestCode, componentSpecified);
-        r.startTime = SystemClock.uptimeMillis();
 
         HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
                 != 0 ? r : null;
@@ -4095,7 +4107,8 @@
             }
         }
 
-        StringBuilder info = new StringBuilder();
+        StringBuilder info = mStringBuilder;
+        info.setLength(0);
         info.append("ANR (application not responding) in process: ");
         info.append(app.processName);
         if (annotation != null) {
@@ -4517,7 +4530,7 @@
             }
         } else if (mStartingProcesses.size() > 0) {
             app = mStartingProcesses.remove(0);
-            app.pid = pid;
+            app.setPid(pid);
         } else {
             app = null;
         }
@@ -7877,24 +7890,24 @@
                 return;
             }
             pw.println("Activities in Current Activity Manager State:");
-            dumpHistoryList(pw, mHistory, "  ", "History");
+            dumpHistoryList(pw, mHistory, "  ", "Hist", true);
             pw.println(" ");
             pw.println("  Running activities (most recent first):");
-            dumpHistoryList(pw, mLRUActivities, "  ", "Running");
+            dumpHistoryList(pw, mLRUActivities, "  ", "Run", false);
             if (mWaitingVisibleActivities.size() > 0) {
                 pw.println(" ");
                 pw.println("  Activities waiting for another to become visible:");
-                dumpHistoryList(pw, mWaitingVisibleActivities, "  ", "Waiting");
+                dumpHistoryList(pw, mWaitingVisibleActivities, "  ", "Wait", false);
             }
             if (mStoppingActivities.size() > 0) {
                 pw.println(" ");
                 pw.println("  Activities waiting to stop:");
-                dumpHistoryList(pw, mStoppingActivities, "  ", "Stopping");
+                dumpHistoryList(pw, mStoppingActivities, "  ", "Stop", false);
             }
             if (mFinishingActivities.size() > 0) {
                 pw.println(" ");
                 pw.println("  Activities waiting to finish:");
-                dumpHistoryList(pw, mFinishingActivities, "  ", "Finishing");
+                dumpHistoryList(pw, mFinishingActivities, "  ", "Fin", false);
             }
 
             pw.println(" ");
@@ -7909,7 +7922,9 @@
 
                 final int N = mRecentTasks.size();
                 for (int i=0; i<N; i++) {
-                    pw.println("  Recent Task #" + i);
+                    TaskRecord tr = mRecentTasks.get(i);
+                    pw.print("  * Recent #"); pw.print(i); pw.print(": ");
+                            pw.println(tr);
                     mRecentTasks.get(i).dump(pw, "    ");
                 }
             }
@@ -7931,8 +7946,9 @@
                         needSep = true;
                     }
                     ProcessRecord r = procs.valueAt(ia);
-                    pw.println((r.persistent ? "  *PERSISTENT* Process [" : "  Process [")
-                            + r.processName + "] UID " + procs.keyAt(ia));
+                    pw.print(r.persistent ? "  *PERS*" : "  *APP*");
+                        pw.print(" UID "); pw.print(procs.keyAt(ia));
+                        pw.print(" "); pw.println(r);
                     r.dump(pw, "    ");
                     if (r.persistent) {
                         numPers++;
@@ -7945,7 +7961,7 @@
                 needSep = true;
                 pw.println("  Running processes (most recent first):");
                 dumpProcessList(pw, mLRUProcesses, "    ",
-                        "Running Norm Proc", "Running PERS Proc", true);
+                        "App ", "PERS", true);
                 needSep = true;
             }
 
@@ -7955,8 +7971,8 @@
                     needSep = true;
                     pw.println("  PID mappings:");
                     for (int i=0; i<mPidsSelfLocked.size(); i++) {
-                        pw.println("    PID #" + mPidsSelfLocked.keyAt(i)
-                                + ": " + mPidsSelfLocked.valueAt(i));
+                        pw.print("    PID #"); pw.print(mPidsSelfLocked.keyAt(i));
+                            pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
                     }
                 }
             }
@@ -7966,8 +7982,8 @@
                 needSep = true;
                 pw.println("  Foreground Processes:");
                 for (int i=0; i<mForegroundProcesses.size(); i++) {
-                    pw.println("    PID #" + mForegroundProcesses.keyAt(i)
-                            + ": " + mForegroundProcesses.valueAt(i));
+                    pw.print("    PID #"); pw.print(mForegroundProcesses.keyAt(i));
+                            pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
                 }
             }
             
@@ -7976,7 +7992,7 @@
                 needSep = true;
                 pw.println("  Persisent processes that are starting:");
                 dumpProcessList(pw, mPersistentStartingProcesses, "    ",
-                        "Starting Initial Proc", "Restarting PERS Proc", false);
+                        "Starting Norm", "Restarting PERS", false);
             }
 
             if (mStartingProcesses.size() > 0) {
@@ -7984,7 +8000,7 @@
                 needSep = true;
                 pw.println("  Processes that are starting:");
                 dumpProcessList(pw, mStartingProcesses, "    ",
-                        "Starting Norm Proc", "Starting PERS Proc", false);
+                        "Starting Norm", "Starting PERS", false);
             }
 
             if (mRemovedProcesses.size() > 0) {
@@ -7992,7 +8008,7 @@
                 needSep = true;
                 pw.println("  Processes that are being removed:");
                 dumpProcessList(pw, mRemovedProcesses, "    ",
-                        "Removed Norm Proc", "Removed PERS Proc", false);
+                        "Removed Norm", "Removed PERS", false);
             }
             
             if (mProcessesOnHold.size() > 0) {
@@ -8000,7 +8016,7 @@
                 needSep = true;
                 pw.println("  Processes that are on old until the system is ready:");
                 dumpProcessList(pw, mProcessesOnHold, "    ",
-                        "OnHold Norm Proc", "OnHold PERS Proc", false);
+                        "OnHold Norm", "OnHold PERS", false);
             }
 
             if (mProcessCrashTimes.getMap().size() > 0) {
@@ -8013,10 +8029,11 @@
                     SparseArray<Long> uids = procs.getValue();
                     final int N = uids.size();
                     for (int i=0; i<N; i++) {
-                        pw.println("    Process " + procs.getKey()
-                                + " uid " + uids.keyAt(i)
-                                + ": last crashed "
-                                + (now-uids.valueAt(i)) + " ms ago");
+                        pw.print("    Process "); pw.print(procs.getKey());
+                                pw.print(" uid "); pw.print(uids.keyAt(i));
+                                pw.print(": last crashed ");
+                                pw.print((now-uids.valueAt(i)));
+                                pw.println(" ms ago");
                     }
                 }
             }
@@ -8030,9 +8047,10 @@
                     SparseArray<Long> uids = procs.getValue();
                     final int N = uids.size();
                     for (int i=0; i<N; i++) {
-                        pw.println("    Bad process " + procs.getKey()
-                                + " uid " + uids.keyAt(i)
-                                + ": crashed at time " + uids.valueAt(i));
+                        pw.print("    Bad process "); pw.print(procs.getKey());
+                                pw.print(" uid "); pw.print(uids.keyAt(i));
+                                pw.print(": crashed at time ");
+                                pw.println(uids.valueAt(i));
                     }
                 }
             }
@@ -8131,14 +8149,14 @@
                 Iterator it = mRegisteredReceivers.values().iterator();
                 while (it.hasNext()) {
                     ReceiverList r = (ReceiverList)it.next();
-                    pw.println("  Receiver " + r.receiver);
+                    pw.print("  * "); pw.println(r);
                     r.dump(pw, "    ");
                 }
             }
 
             pw.println(" ");
             pw.println("Receiver Resolver Table:");
-            mReceiverResolver.dump(new PrintWriterPrinter(pw), "  ");
+            mReceiverResolver.dump(pw, "  ");
             
             if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
                     || mPendingBroadcast != null) {
@@ -8172,13 +8190,23 @@
             if (mStickyBroadcasts != null) {
                 pw.println(" ");
                 pw.println("  Sticky broadcasts:");
+                StringBuilder sb = new StringBuilder(128);
                 for (Map.Entry<String, ArrayList<Intent>> ent
                         : mStickyBroadcasts.entrySet()) {
-                    pw.println("  Sticky action " + ent.getKey() + ":");
+                    pw.print("  * Sticky action "); pw.print(ent.getKey());
+                            pw.println(":");
                     ArrayList<Intent> intents = ent.getValue();
                     final int N = intents.size();
                     for (int i=0; i<N; i++) {
-                        pw.println("    " + intents.get(i));
+                        sb.setLength(0);
+                        sb.append("    Intent: ");
+                        intents.get(i).toShortString(sb, true, false);
+                        pw.println(sb.toString());
+                        Bundle bundle = intents.get(i).getExtras();
+                        if (bundle != null) {
+                            pw.print("      ");
+                            pw.println(bundle.toString());
+                        }
                     }
                 }
             }
@@ -8209,7 +8237,7 @@
                 Iterator<ServiceRecord> it = mServices.values().iterator();
                 while (it.hasNext()) {
                     ServiceRecord r = it.next();
-                    pw.println("  Service " + r.shortName);
+                    pw.print("  * "); pw.println(r);
                     r.dump(pw, "    ");
                 }
                 needSep = true;
@@ -8220,7 +8248,7 @@
                 pw.println("  Pending services:");
                 for (int i=0; i<mPendingServices.size(); i++) {
                     ServiceRecord r = mPendingServices.get(i);
-                    pw.println("  Pending Service " + r.shortName);
+                    pw.print("  * Pending "); pw.println(r);
                     r.dump(pw, "    ");
                 }
                 needSep = true;
@@ -8231,7 +8259,7 @@
                 pw.println("  Restarting services:");
                 for (int i=0; i<mRestartingServices.size(); i++) {
                     ServiceRecord r = mRestartingServices.get(i);
-                    pw.println("  Restarting Service " + r.shortName);
+                    pw.print("  * Restarting "); pw.println(r);
                     r.dump(pw, "    ");
                 }
                 needSep = true;
@@ -8242,7 +8270,7 @@
                 pw.println("  Stopping services:");
                 for (int i=0; i<mStoppingServices.size(); i++) {
                     ServiceRecord r = mStoppingServices.get(i);
-                    pw.println("  Stopping Service " + r.shortName);
+                    pw.print("  * Stopping "); pw.println(r);
                     r.dump(pw, "    ");
                 }
                 needSep = true;
@@ -8255,8 +8283,7 @@
                         = mServiceConnections.values().iterator();
                 while (it.hasNext()) {
                     ConnectionRecord r = it.next();
-                    pw.println("  " + r.binding.service.shortName
-                          + " -> " + r.conn.asBinder());
+                    pw.print("  * "); pw.println(r);
                     r.dump(pw, "    ");
                 }
             }
@@ -8279,18 +8306,6 @@
 
             boolean needSep = false;
 
-            if (mProvidersByName.size() > 0) {
-                pw.println("  Published content providers (by name):");
-                Iterator it = mProvidersByName.entrySet().iterator();
-                while (it.hasNext()) {
-                    Map.Entry e = (Map.Entry)it.next();
-                    ContentProviderRecord r = (ContentProviderRecord)e.getValue();
-                    pw.println("  Provider " + (String)e.getKey());
-                    r.dump(pw, "    ");
-                }
-                needSep = true;
-            }
-
             if (mProvidersByClass.size() > 0) {
                 if (needSep) pw.println(" ");
                 pw.println("  Published content providers (by class):");
@@ -8298,31 +8313,48 @@
                 while (it.hasNext()) {
                     Map.Entry e = (Map.Entry)it.next();
                     ContentProviderRecord r = (ContentProviderRecord)e.getValue();
-                    pw.println("  Provider " + (String)e.getKey());
+                    pw.print("  * "); pw.println(r);
                     r.dump(pw, "    ");
                 }
                 needSep = true;
             }
 
+            if (mProvidersByName.size() > 0) {
+                pw.println(" ");
+                pw.println("  Authority to provider mappings:");
+                Iterator it = mProvidersByName.entrySet().iterator();
+                while (it.hasNext()) {
+                    Map.Entry e = (Map.Entry)it.next();
+                    ContentProviderRecord r = (ContentProviderRecord)e.getValue();
+                    pw.print("  "); pw.print(e.getKey()); pw.print(": ");
+                            pw.println(r);
+                }
+                needSep = true;
+            }
+
             if (mLaunchingProviders.size() > 0) {
                 if (needSep) pw.println(" ");
                 pw.println("  Launching content providers:");
                 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
-                    pw.println("  Provider #" + i + ":");
-                    ((ContentProviderRecord)mLaunchingProviders.get(i)).dump(pw, "    ");
+                    pw.print("  Launching #"); pw.print(i); pw.print(": ");
+                            pw.println(mLaunchingProviders.get(i));
                 }
                 needSep = true;
             }
 
-            pw.println();
-            pw.println("Granted Uri Permissions:");
-            for (int i=0; i<mGrantedUriPermissions.size(); i++) {
-                int uid = mGrantedUriPermissions.keyAt(i);
-                HashMap<Uri, UriPermission> perms
-                        = mGrantedUriPermissions.valueAt(i);
-                pw.println("  Uris granted to uid " + uid + ":");
-                for (UriPermission perm : perms.values()) {
-                    perm.dump(pw, "    ");
+            if (mGrantedUriPermissions.size() > 0) {
+                pw.println();
+                pw.println("Granted Uri Permissions:");
+                for (int i=0; i<mGrantedUriPermissions.size(); i++) {
+                    int uid = mGrantedUriPermissions.keyAt(i);
+                    HashMap<Uri, UriPermission> perms
+                            = mGrantedUriPermissions.valueAt(i);
+                    pw.print("  * UID "); pw.print(uid);
+                            pw.println(" holds:");
+                    for (UriPermission perm : perms.values()) {
+                        pw.print("    "); pw.println(perm);
+                        perm.dump(pw, "      ");
+                    }
                 }
             }
         }
@@ -8340,7 +8372,7 @@
                 return;
             }
 
-            pw.println("Intent Senders in Current Activity Manager State:");
+            pw.println("Pending Intents in Current Activity Manager State:");
 
             if (this.mIntentSenderRecords.size() > 0) {
                 Iterator<WeakReference<PendingIntentRecord>> it
@@ -8349,10 +8381,10 @@
                     WeakReference<PendingIntentRecord> ref = it.next();
                     PendingIntentRecord rec = ref != null ? ref.get(): null;
                     if (rec != null) {
-                        pw.println("  IntentSender " + rec);
+                        pw.print("  * "); pw.println(rec);
                         rec.dump(pw, "    ");
                     } else {
-                        pw.println("  IntentSender " + ref);
+                        pw.print("  * "); pw.print(ref);
                     }
                 }
             }
@@ -8360,16 +8392,26 @@
     }
 
     private static final void dumpHistoryList(PrintWriter pw, List list,
-            String prefix, String label) {
+            String prefix, String label, boolean complete) {
         TaskRecord lastTask = null;
         for (int i=list.size()-1; i>=0; i--) {
             HistoryRecord r = (HistoryRecord)list.get(i);
+            final boolean full = complete || !r.inHistory;
             if (lastTask != r.task) {
                 lastTask = r.task;
-                lastTask.dump(pw, prefix + "  ");
+                pw.print(prefix);
+                pw.print(full ? "* " : "  ");
+                pw.println(lastTask);
+                if (full) {
+                    lastTask.dump(pw, prefix + "  ");
+                }
             }
-            pw.println(prefix + "    " + label + " #" + i + ":");
-            r.dump(pw, prefix + "      ");
+            pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
+            pw.print(" #"); pw.print(i); pw.print(": ");
+            pw.println(r);
+            if (full) {
+                r.dump(pw, prefix + "      ");
+            }
         }
     }
 
@@ -8401,7 +8443,7 @@
 
     private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
             PrintWriter pw, List list, String prefix, String[] args) {
-        final boolean isCheckinRequest = scanArgs(args, "-c");
+        final boolean isCheckinRequest = scanArgs(args, "--checkin");
         long uptime = SystemClock.uptimeMillis();
         long realtime = SystemClock.elapsedRealtime();
         
@@ -8738,7 +8780,7 @@
                 mPidsSelfLocked.remove(app.pid);
                 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             }
-            app.pid = 0;
+            app.setPid(0);
         }
     }
 
diff --git a/services/java/com/android/server/am/AppBindRecord.java b/services/java/com/android/server/am/AppBindRecord.java
index ce6f6dc..9c57360 100644
--- a/services/java/com/android/server/am/AppBindRecord.java
+++ b/services/java/com/android/server/am/AppBindRecord.java
@@ -32,9 +32,12 @@
                                     // All ConnectionRecord for this client.
 
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
         pw.println(prefix + "service=" + service);
         pw.println(prefix + "client=" + client);
+        dumpInIntentBind(pw, prefix);
+    }
+
+    void dumpInIntentBind(PrintWriter pw, String prefix) {
         if (connections.size() > 0) {
             pw.println(prefix + "Per-process Connections:");
             Iterator<ConnectionRecord> it = connections.iterator();
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 9ad994c..ddc3e68 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -264,6 +264,11 @@
         mStats.setOnBattery(onBattery, level);
     }
     
+    public void recordCurrentLevel(int level) {
+        enforceCallingPermission();
+        mStats.recordCurrentLevel(level);
+    }
+    
     public long getAwakeTimeBattery() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BATTERY_STATS, null);
@@ -290,14 +295,14 @@
             boolean isCheckin = false;
             if (args != null) {
                 for (String arg : args) {
-                    if ("-c".equals(arg)) {
+                    if ("--checkin".equals(arg)) {
                         isCheckin = true;
                         break;
                     }
                 }
             }
             if (isCheckin) mStats.dumpCheckinLocked(pw, args);
-            else mStats.dumpLocked(new PrintWriterPrinter(pw));
+            else mStats.dumpLocked(pw);
         }
     }
 }
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index cd7f720..0eeb393 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -18,6 +18,7 @@
 
 import android.content.IntentFilter;
 import android.util.PrintWriterPrinter;
+import android.util.Printer;
 
 import java.io.PrintWriter;
 
@@ -33,19 +34,25 @@
         requiredPermission = _requiredPermission;
     }
     
-    public void dumpLocal(PrintWriter pw, String prefix) {
-        super.dump(new PrintWriterPrinter(pw), prefix);
-    }
-    
     public void dump(PrintWriter pw, String prefix) {
-        dumpLocal(pw, prefix);
-        pw.println(prefix + "requiredPermission=" + requiredPermission);
+        dumpInReceiverList(pw, new PrintWriterPrinter(pw), prefix);
         receiverList.dumpLocal(pw, prefix);
     }
     
+    public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) {
+        super.dump(pr, prefix);
+        if (requiredPermission != null) {
+            pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
+        }
+    }
+    
     public String toString() {
-        return "BroadcastFilter{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + receiverList + "}";
+        StringBuilder sb = new StringBuilder();
+        sb.append("BroadcastFilter{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(receiverList);
+        sb.append('}');
+        return sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 41a783f..b3343dd 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -28,11 +28,13 @@
     final HistoryRecord activity;   // If non-null, the owning activity.
     final IServiceConnection conn;  // The client connection.
     final int flags;                // Binding options.
-
+    String stringName;              // Caching of toString.
+    
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
         pw.println(prefix + "binding=" + binding);
-        pw.println(prefix + "activity=" + activity);
+        if (activity != null) {
+            pw.println(prefix + "activity=" + activity);
+        }
         pw.println(prefix + "conn=" + conn.asBinder()
                 + " flags=0x" + Integer.toHexString(flags));
     }
@@ -46,9 +48,17 @@
     }
 
     public String toString() {
-        return "ConnectionRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + binding.service.shortName
-            + ":@" + Integer.toHexString(System.identityHashCode(conn.asBinder())) + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ConnectionRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(binding.service.shortName);
+        sb.append(":@");
+        sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index 9f37c14..c764635 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -32,7 +32,8 @@
     int externals;     // number of non-framework processes supported by this provider
     ProcessRecord app; // if non-null, hosting application
     ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
-
+    String stringName;
+    
     public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) {
         super(_info);
         uid = ai.uid;
@@ -53,24 +54,39 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "package=" + info.applicationInfo.packageName
-              + " process=" + info.processName);
-        pw.println(prefix + "app=" + app);
-        pw.println(prefix + "launchingApp=" + launchingApp);
-        pw.println(prefix + "provider=" + provider);
-        pw.println(prefix + "name=" + info.authority);
-        pw.println(prefix + "isSyncable=" + info.isSyncable);
-        pw.println(prefix + "multiprocess=" + info.multiprocess
-              + " initOrder=" + info.initOrder
-              + " uid=" + uid);
-        pw.println(prefix + "clients=" + clients);
-        pw.println(prefix + "externals=" + externals);
+        pw.print(prefix); pw.print("package=");
+                pw.print(info.applicationInfo.packageName);
+                pw.print("process="); pw.println(info.processName);
+        pw.print(prefix); pw.print("app="); pw.println(app);
+        if (launchingApp != null) {
+            pw.print(prefix); pw.print("launchingApp="); pw.println(launchingApp);
+        }
+        pw.print(prefix); pw.print("uid="); pw.print(uid);
+                pw.print(" provider="); pw.println(provider);
+        pw.print(prefix); pw.print("name="); pw.println(info.authority);
+        if (info.isSyncable || info.multiprocess || info.initOrder != 0) {
+            pw.print(prefix); pw.print("isSyncable="); pw.print(info.isSyncable);
+                    pw.print("multiprocess="); pw.print(info.multiprocess);
+                    pw.print(" initOrder="); pw.println(info.initOrder);
+        }
+        if (clients.size() > 0) {
+            pw.print(prefix); pw.print("clients="); pw.println(clients);
+        }
+        if (externals != 0) {
+            pw.print(prefix); pw.print("externals="); pw.println(externals);
+        }
     }
 
     public String toString() {
-        return "ContentProviderRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + info.name + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ContentProviderRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(info.name);
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 0f62471..1488791 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -100,46 +100,74 @@
     boolean hasBeenLaunched;// has this activity ever been launched?
     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
 
+    String stringName;      // for caching of toString().
+    
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "packageName=" + packageName
-              + " processName=" + processName);
-        pw.println(prefix + "launchedFromUid=" + launchedFromUid
-                + " app=" + app);
-        pw.println(prefix + intent);
-        pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
-        pw.println(prefix + "taskAffinity=" + taskAffinity);
-        pw.println(prefix + "realActivity=" + realActivity);
-        pw.println(prefix + "dir=" + baseDir + " res=" + resDir + " data=" + dataDir);
-        pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
-                + " icon=0x" + Integer.toHexString(icon)
-                + " theme=0x" + Integer.toHexString(theme));
-        pw.println(prefix + "stateNotNeeded=" + stateNotNeeded
-                + " componentSpecified=" + componentSpecified
-                + " isHomeActivity=" + isHomeActivity);
-        pw.println(prefix + "configuration=" + configuration);
-        pw.println(prefix + "resultTo=" + resultTo
-              + " resultWho=" + resultWho + " resultCode=" + requestCode);
-        pw.println(prefix + "results=" + results);
-        pw.println(prefix + "pendingResults=" + pendingResults);
-        pw.println(prefix + "readUriPermissions=" + readUriPermissions);
-        pw.println(prefix + "writeUriPermissions=" + writeUriPermissions);
-        pw.println(prefix + "launchFailed=" + launchFailed
-              + " haveState=" + haveState + " icicle=" + icicle);
-        pw.println(prefix + "state=" + state
-              + " stopped=" + stopped + " finishing=" + finishing);
-        pw.println(prefix + "keysPaused=" + keysPaused
-              + " inHistory=" + inHistory + " persistent=" + persistent
-              + " launchMode=" + launchMode);
-        pw.println(prefix + "fullscreen=" + fullscreen
-              + " visible=" + visible
-              + " frozenBeforeDestroy=" + frozenBeforeDestroy
-              + " thumbnailNeeded=" + thumbnailNeeded + " idle=" + idle);
-        pw.println(prefix + "waitingVisible=" + waitingVisible
-              + " nowVisible=" + nowVisible);
-        pw.println(prefix + "configDestroy=" + configDestroy
-                + " configChangeFlags=" + Integer.toHexString(configChangeFlags));
-        pw.println(prefix + "connections=" + connections);
+        pw.print(prefix); pw.print("packageName="); pw.print(packageName);
+                pw.print(" processName="); pw.println(processName);
+        pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
+                pw.print(" app="); pw.println(app);
+        pw.print(prefix); pw.println(intent);
+        pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
+                pw.print(" task="); pw.println(task);
+        pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
+        pw.print(prefix); pw.print("realActivity=");
+                pw.println(realActivity.flattenToShortString());
+        pw.print(prefix); pw.print("base="); pw.print(baseDir);
+                if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir);
+                pw.print(" data="); pw.println(dataDir);
+        pw.print(prefix); pw.print("labelRes=0x");
+                pw.print(Integer.toHexString(labelRes));
+                pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
+                pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
+        pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
+                pw.print(" componentSpecified="); pw.print(componentSpecified);
+                pw.print(" isHomeActivity="); pw.println(isHomeActivity);
+        pw.print(prefix); pw.print("configuration="); pw.println(configuration);
+        if (resultTo != null || resultWho != null) {
+            pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
+                    pw.print(" resultWho="); pw.print(resultWho);
+                    pw.print(" resultCode="); pw.println(requestCode);
+        }
+        if (results != null) {
+            pw.print(prefix); pw.print("results="); pw.println(results);
+        }
+        if (pendingResults != null) {
+            pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
+        }
+        if (readUriPermissions != null) {
+            pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
+        }
+        if (writeUriPermissions != null) {
+            pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
+        }
+        pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
+                pw.print(" haveState="); pw.print(haveState);
+                pw.print(" icicle="); pw.println(icicle);
+        pw.print(prefix); pw.print("state="); pw.print(state);
+                pw.print(" stopped="); pw.print(stopped);
+                pw.print(" finishing="); pw.println(finishing);
+        pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
+                pw.print(" inHistory="); pw.print(inHistory);
+                pw.print(" persistent="); pw.print(persistent);
+                pw.print(" launchMode="); pw.println(launchMode);
+        pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
+                pw.print(" visible="); pw.print(visible);
+                pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
+                pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
+                pw.print(" idle="); pw.println(idle);
+        if (waitingVisible || nowVisible) {
+            pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
+                    pw.print(" nowVisible="); pw.println(nowVisible);
+        }
+        if (configDestroy || configChangeFlags != 0) {
+            pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
+                    pw.print(" configChangeFlags=");
+                    pw.println(Integer.toHexString(configChangeFlags));
+        }
+        if (connections != null) {
+            pw.print(prefix); pw.print("connections="); pw.println(connections);
+        }
     }
 
     HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
@@ -335,15 +363,31 @@
     
     public void windowsVisible() {
         synchronized(service) {
-            if (ActivityManagerService.SHOW_ACTIVITY_START_TIME
-                    && startTime != 0) {
-                long time = SystemClock.uptimeMillis() - startTime;
-                EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
-                        System.identityHashCode(this), shortComponentName, time);
-                Log.i(ActivityManagerService.TAG, "Displayed activity "
-                        + shortComponentName
-                        + ": " + time + " ms");
+            if (startTime != 0) {
+                final long curTime = SystemClock.uptimeMillis();
+                final long thisTime = curTime - startTime;
+                final long totalTime = service.mInitialStartTime != 0
+                        ? (curTime - service.mInitialStartTime) : thisTime;
+                if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
+                    EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
+                            System.identityHashCode(this), shortComponentName,
+                            thisTime, totalTime);
+                    StringBuilder sb = service.mStringBuilder;
+                    sb.setLength(0);
+                    sb.append("Displayed activity ");
+                    sb.append(shortComponentName);
+                    sb.append(": ");
+                    sb.append(thisTime);
+                    sb.append(" ms (total ");
+                    sb.append(totalTime);
+                    sb.append(" ms)");
+                    Log.i(ActivityManagerService.TAG, sb.toString());
+                }
+                if (totalTime > 0) {
+                    service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
+                }
                 startTime = 0;
+                service.mInitialStartTime = 0;
             }
             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
                     ActivityManagerService.TAG, "windowsVisible(): " + this);
@@ -453,8 +497,15 @@
     
     
     public String toString() {
-        return "HistoryRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + intent.getComponent().toShortString() + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("HistoryRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(intent.getComponent().flattenToShortString());
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/IntentBindRecord.java b/services/java/com/android/server/am/IntentBindRecord.java
index 24c3943..3a5ca66 100644
--- a/services/java/com/android/server/am/IntentBindRecord.java
+++ b/services/java/com/android/server/am/IntentBindRecord.java
@@ -45,22 +45,30 @@
     /** Set when the service's onUnbind() has asked to be told about new clients. */
     boolean doRebind;
     
+    String stringName;      // caching of toString
+    
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "service=" + service);
-        pw.println(prefix + "intent=" + intent.getIntent());
-        pw.println(prefix + "binder=" + binder
-                + " requested=" + requested
-                + " received=" + received
-                + " hasBound=" + hasBound
-                + " doRebind=" + doRebind);
+        pw.print(prefix); pw.print("service="); pw.println(service);
+        dumpInService(pw, prefix);
+    }
+
+    void dumpInService(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("intent={");
+                pw.print(intent.getIntent().toShortString(true, false));
+                pw.println('}');
+        pw.print(prefix); pw.print("binder="); pw.println(binder);
+        pw.print(prefix); pw.print("requested="); pw.print(requested);
+                pw.print(" received="); pw.print(received);
+                pw.print(" hasBound="); pw.print(hasBound);
+                pw.print(" doRebind="); pw.println(doRebind);
         if (apps.size() > 0) {
-            pw.println(prefix + "Application Bindings:");
             Iterator<AppBindRecord> it = apps.values().iterator();
             while (it.hasNext()) {
                 AppBindRecord a = it.next();
-                pw.println(prefix + "Client " + a.client);
-                a.dump(pw, prefix + "  ");
+                pw.print(prefix); pw.print("* Client AppBindRecord{");
+                        pw.print(Integer.toHexString(System.identityHashCode(a)));
+                        pw.print(' '); pw.print(a.client); pw.println('}');
+                a.dumpInIntentBind(pw, prefix + "  ");
             }
         }
     }
@@ -71,9 +79,19 @@
     }
 
     public String toString() {
-        return "IntentBindRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + service.name.toShortString()
-            + ":" + intent + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("IntentBindRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(service.shortName);
+        sb.append(':');
+        if (intent != null) {
+            intent.getIntent().toShortString(sb, false, false);
+        }
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index b18aaf7..4381392 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -36,6 +36,8 @@
     boolean sent = false;
     boolean canceled = false;
 
+    String stringName;
+    
     final static class Key {
         final int type;
         final String packageName;
@@ -142,7 +144,7 @@
         
         public String toString() {
             return "Key{" + typeName() + " pkg=" + packageName
-                + " intent=" + requestIntent + " flags=0x"
+                + " intent=" + requestIntent.toShortString(true, false) + " flags=0x"
                 + Integer.toHexString(flags) + "}";
         }
         
@@ -260,19 +262,38 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + "packageName=" + key.packageName
-                + " type=" + key.typeName()
-                + " flags=0x" + Integer.toHexString(key.flags));
-        pw.println(prefix + "activity=" + key.activity + " who=" + key.who);
-        pw.println(prefix + "requestCode=" + key.requestCode
-                + " requestResolvedType=" + key.requestResolvedType);
-        pw.println(prefix + "requestIntent=" + key.requestIntent);
-        pw.println(prefix + "sent=" + sent + " canceled=" + canceled);
+        pw.print(prefix); pw.print("uid="); pw.print(uid);
+                pw.print(" packageName="); pw.print(key.packageName);
+                pw.print(" type="); pw.print(key.typeName());
+                pw.print(" flags=0x"); pw.println(Integer.toHexString(key.flags));
+        if (key.activity != null || key.who != null) {
+            pw.print(prefix); pw.print("activity="); pw.print(key.activity);
+                    pw.print(" who="); pw.println(key.who);
+        }
+        if (key.requestCode != 0 || key.requestResolvedType != null) {
+            pw.print(prefix); pw.print("requestCode="); pw.print(key.requestCode);
+                    pw.print(" requestResolvedType="); pw.println(key.requestResolvedType);
+        }
+        pw.print(prefix); pw.print("requestIntent=");
+                pw.println(key.requestIntent.toShortString(true, true));
+        if (sent || canceled) {
+            pw.print(prefix); pw.print("sent="); pw.print(sent);
+                    pw.print(" canceled="); pw.println(canceled);
+        }
     }
 
     public String toString() {
-        return "IntentSenderRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + key.packageName + " " + key.typeName() + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("PendingIntentRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(key.packageName);
+        sb.append(' ');
+        sb.append(key.typeName());
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index a1320df..b76547a 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -98,44 +98,81 @@
     boolean waitedForDebugger;  // has process show wait for debugger dialog?
     Dialog waitDialog;          // current wait for debugger dialog
     
+    String stringName;          // caching of toString() result.
+    
     // These reports are generated & stored when an app gets into an error condition.
     // They will be "null" when all is OK.
     ActivityManager.ProcessErrorStateInfo crashingReport;
     ActivityManager.ProcessErrorStateInfo notRespondingReport;
 
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "class=" + info.className);
-        pw.println(prefix+"manageSpaceActivityName="+info.manageSpaceActivityName);
-        pw.println(prefix + "dir=" + info.sourceDir + " publicDir=" + info.publicSourceDir 
-              + " data=" + info.dataDir);
-        pw.println(prefix + "packageList=" + pkgList);
-        pw.println(prefix + "instrumentationClass=" + instrumentationClass
-              + " instrumentationProfileFile=" + instrumentationProfileFile);
-        pw.println(prefix + "instrumentationArguments=" + instrumentationArguments);
-        pw.println(prefix + "thread=" + thread + " curReceiver=" + curReceiver);
-        pw.println(prefix + "pid=" + pid + " starting=" + starting
-                + " lastPss=" + lastPss);
-        pw.println(prefix + "maxAdj=" + maxAdj + " hiddenAdj=" + hiddenAdj
-                + " curRawAdj=" + curRawAdj + " setRawAdj=" + setRawAdj
-                + " curAdj=" + curAdj + " setAdj=" + setAdj);
-        pw.println(prefix + "isForeground=" + isForeground
-                + " setIsForeground=" + setIsForeground
-                + " foregroundServices=" + foregroundServices
-                + " forcingToForeground=" + forcingToForeground);
-        pw.println(prefix + "persistent=" + persistent + " removed=" + removed
-                + " persistentActivities=" + persistentActivities);
-        pw.println(prefix + "debugging=" + debugging
-                + " crashing=" + crashing + " " + crashDialog
-                + " notResponding=" + notResponding + " " + anrDialog
-                + " bad=" + bad);
-        pw.println(prefix + "activities=" + activities);
-        pw.println(prefix + "services=" + services);
-        pw.println(prefix + "executingServices=" + executingServices);
-        pw.println(prefix + "connections=" + connections);
-        pw.println(prefix + "pubProviders=" + pubProviders);
-        pw.println(prefix + "conProviders=" + conProviders);
-        pw.println(prefix + "receivers=" + receivers);
+        if (info.className != null) {
+            pw.print(prefix); pw.print("class="); pw.println(info.className);
+        }
+        if (info.manageSpaceActivityName != null) {
+            pw.print(prefix); pw.print("manageSpaceActivityName=");
+            pw.println(info.manageSpaceActivityName);
+        }
+        pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);
+                pw.print(" publicDir="); pw.print(info.publicSourceDir);
+                pw.print(" data="); pw.println(info.dataDir);
+        pw.print(prefix); pw.print("packageList="); pw.println(pkgList);
+        if (instrumentationClass != null || instrumentationProfileFile != null
+                || instrumentationArguments != null) {
+            pw.print(prefix); pw.print("instrumentationClass=");
+                    pw.print(instrumentationClass);
+                    pw.print(" instrumentationProfileFile=");
+                    pw.println(instrumentationProfileFile);
+            pw.print(prefix); pw.print("instrumentationArguments=");
+                    pw.println(instrumentationArguments);
+        }
+        pw.print(prefix); pw.print("thread="); pw.print(thread);
+                pw.print(" curReceiver="); pw.println(curReceiver);
+        pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
+                pw.print(starting); pw.print(" lastPss="); pw.println(lastPss);
+        pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
+                pw.print(" hidden="); pw.print(hiddenAdj);
+                pw.print(" curRaw="); pw.print(curRawAdj);
+                pw.print(" setRaw="); pw.print(setRawAdj);
+                pw.print(" cur="); pw.print(curAdj);
+                pw.print(" set="); pw.println(setAdj);
+        pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
+                pw.print(" setIsForeground="); pw.print(setIsForeground);
+                pw.print(" foregroundServices="); pw.print(foregroundServices);
+                pw.print(" forcingToForeground="); pw.println(forcingToForeground);
+        pw.print(prefix); pw.print("persistent="); pw.print(persistent);
+                pw.print(" removed="); pw.print(removed);
+                pw.print(" persistentActivities="); pw.println(persistentActivities);
+        if (debugging || crashing || crashDialog != null || notResponding
+                || anrDialog != null || bad) {
+            pw.print(prefix); pw.print("debugging="); pw.print(debugging);
+                    pw.print(" crashing="); pw.print(crashing);
+                    pw.print(" "); pw.print(crashDialog);
+                    pw.print(" notResponding="); pw.print(notResponding);
+                    pw.print(" " ); pw.print(anrDialog);
+                    pw.print(" bad="); pw.println(bad);
+        }
+        if (activities.size() > 0) {
+            pw.print(prefix); pw.print("activities="); pw.println(activities);
+        }
+        if (services.size() > 0) {
+            pw.print(prefix); pw.print("services="); pw.println(services);
+        }
+        if (executingServices.size() > 0) {
+            pw.print(prefix); pw.print("executingServices="); pw.println(executingServices);
+        }
+        if (connections.size() > 0) {
+            pw.print(prefix); pw.print("connections="); pw.println(connections);
+        }
+        if (pubProviders.size() > 0) {
+            pw.print(prefix); pw.print("pubProviders="); pw.println(pubProviders);
+        }
+        if (conProviders.size() > 0) {
+            pw.print(prefix); pw.print("conProviders="); pw.println(conProviders);
+        }
+        if (receivers.size() > 0) {
+            pw.print(prefix); pw.print("receivers="); pw.println(receivers);
+        }
     }
     
     ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
@@ -154,6 +191,11 @@
         persistentActivities = 0;
     }
 
+    public void setPid(int _pid) {
+        pid = _pid;
+        stringName = null;
+    }
+    
     /**
      * This method returns true if any of the activities within the process record are interesting
      * to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -188,9 +230,20 @@
     }
     
     public String toString() {
-        return "ProcessRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + pid + ":" + processName + "/" + info.uid + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ProcessRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(pid);
+        sb.append(':');
+        sb.append(processName);
+        sb.append('/');
+        sb.append(info.uid);
+        sb.append('}');
+        return stringName = sb.toString();
     }
     
     /*
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 6ac527b..0facefc 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -18,9 +18,12 @@
 
 import android.app.IIntentReceiver;
 import android.content.Intent;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.PrintWriterPrinter;
+import android.util.Printer;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -39,6 +42,8 @@
     BroadcastRecord curBroadcast = null;
     boolean linkedToDeath = false;
 
+    String stringName;
+    
     ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
             int _pid, int _uid, IIntentReceiver _receiver) {
         owner = _owner;
@@ -62,31 +67,45 @@
     }
     
     void dumpLocal(PrintWriter pw, String prefix) {
-        pw.println(prefix + "receiver=IBinder "
-                + Integer.toHexString(System.identityHashCode(receiver.asBinder())));
-        pw.println(prefix + "app=" + app + " pid=" + pid + " uid=" + uid);
-        pw.println(prefix + "curBroadcast=" + curBroadcast
-                + " linkedToDeath=" + linkedToDeath);
+        pw.print(prefix); pw.print("app="); pw.print(app);
+            pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.println(uid);
+        if (curBroadcast != null || linkedToDeath) {
+            pw.print(prefix); pw.print("curBroadcast="); pw.print(curBroadcast);
+                pw.print(" linkedToDeath="); pw.println(linkedToDeath);
+        }
     }
     
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
+        Printer pr = new PrintWriterPrinter(pw);
         dumpLocal(pw, prefix);
         String p2 = prefix + "  ";
         final int N = size();
         for (int i=0; i<N; i++) {
             BroadcastFilter bf = get(i);
-            pw.println(prefix + "Filter #" + i + ": " + bf);
-            bf.dump(pw, p2);
+            pw.print(prefix); pw.print("Filter #"); pw.print(i);
+                    pw.print(": BroadcastFilter{");
+                    pw.print(Integer.toHexString(System.identityHashCode(bf)));
+                    pw.println('}');
+            bf.dumpInReceiverList(pw, pr, p2);
         }
     }
     
     public String toString() {
-        return "ReceiverList{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + pid + " " + (app != null ? app.processName : "(unknown name)")
-            + "/" + uid + " client "
-            + Integer.toHexString(System.identityHashCode(receiver.asBinder()))
-            + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ReceiverList{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(pid);
+        sb.append(' ');
+        sb.append((app != null ? app.processName : "(unknown name)"));
+        sb.append('/');
+        sb.append(uid);
+        sb.append((receiver.asBinder() instanceof Binder) ? " local:" : " remote:");
+        sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder())));
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 4b90600..fc93b69 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -77,41 +77,49 @@
     long restartTime;       // time of last restart.
     long nextRestartTime;   // time when restartDelay will expire.
 
+    String stringName;      // caching of toString
+    
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "intent=" + intent.getIntent());
-        pw.println(prefix + "packageName=" + packageName);
-        pw.println(prefix + "processName=" + processName);
-        pw.println(prefix + "permission=" + permission);
-        pw.println(prefix + "baseDir=" + baseDir+ " resDir=" + resDir + " dataDir=" + dataDir);
-        pw.println(prefix + "app=" + app);
-        pw.println(prefix + "isForeground=" + isForeground
-                + " lastActivity=" + lastActivity);
-        pw.println(prefix + "startRequested=" + startRequested
-              + " startId=" + lastStartId
-              + " executeNesting=" + executeNesting
-              + " executingStart=" + executingStart
-              + " crashCount=" + crashCount);
-        pw.println(prefix + "totalRestartCount=" + totalRestartCount
-                + " restartCount=" + restartCount
-                + " restartDelay=" + restartDelay
-                + " restartTime=" + restartTime
-                + " nextRestartTime=" + nextRestartTime);
+        pw.print(prefix); pw.print("intent={");
+                pw.print(intent.getIntent().toShortString(true, false));
+                pw.println('}');
+        pw.print(prefix); pw.print("packageName="); pw.println(packageName);
+        pw.print(prefix); pw.print("processName="); pw.println(processName);
+        if (permission != null) {
+            pw.print(prefix); pw.print("permission="); pw.println(permission);
+        }
+        pw.print(prefix); pw.print("baseDir="); pw.print(baseDir);
+                if (!resDir.equals(baseDir)) pw.print(" resDir="); pw.print(resDir);
+                pw.print(" dataDir="); pw.println(dataDir);
+        pw.print(prefix); pw.print("app="); pw.println(app);
+        pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
+                pw.print(" lastActivity="); pw.println(lastActivity);
+        pw.print(prefix); pw.print("startRequested="); pw.print(startRequested);
+                pw.print(" startId="); pw.print(lastStartId);
+                pw.print(" executeNesting="); pw.print(executeNesting);
+                pw.print(" executingStart="); pw.print(executingStart);
+                pw.print(" crashCount="); pw.println(crashCount);
+        pw.print(prefix); pw.print("totalRestartCount="); pw.print(totalRestartCount);
+                pw.print(" restartCount="); pw.print(restartCount);
+                pw.print(" restartDelay="); pw.print(restartDelay);
+                pw.print(" restartTime="); pw.print(restartTime);
+                pw.print(" nextRestartTime="); pw.println(nextRestartTime);
         if (bindings.size() > 0) {
-            pw.println(prefix + "Bindings:");
             Iterator<IntentBindRecord> it = bindings.values().iterator();
             while (it.hasNext()) {
                 IntentBindRecord b = it.next();
-                pw.println(prefix + "Binding " + b);
-                b.dump(pw, prefix + "  ");
+                pw.print(prefix); pw.print("* IntentBindRecord{");
+                        pw.print(Integer.toHexString(System.identityHashCode(b)));
+                        pw.println("}:");
+                b.dumpInService(pw, prefix + "  ");
             }
         }
         if (connections.size() > 0) {
-            pw.println(prefix + "All Connections:");
+            pw.print(prefix); pw.println("All Connections:");
             Iterator<ConnectionRecord> it = connections.values().iterator();
             while (it.hasNext()) {
                 ConnectionRecord c = it.next();
-                pw.println(prefix + "  " + c);
+                pw.print(prefix); pw.print("  "); pw.println(c);
             }
         }
     }
@@ -159,8 +167,13 @@
     }
     
     public String toString() {
-        return "ServiceRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + shortName + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ServiceRecord{")
+            .append(Integer.toHexString(System.identityHashCode(this)))
+            .append(' ').append(shortName).append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index aab3736..bcb8f54 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -36,6 +36,8 @@
     boolean rootWasReset;   // True if the intent at the root of the task had
                             // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
 
+    String stringName;      // caching of toString() result.
+    
     TaskRecord(int _taskId, ActivityInfo info, Intent _intent,
             boolean _clearOnBackground) {
         taskId = _taskId;
@@ -53,6 +55,8 @@
     }
     
     void setIntent(Intent _intent, ActivityInfo info) {
+        stringName = null;
+        
         if (info.targetActivity == null) {
             intent = _intent;
             realActivity = _intent != null ? _intent.getComponent() : null;
@@ -82,23 +86,63 @@
     }
     
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "clearOnBackground=" + clearOnBackground
-              + " numActivities=" + numActivities
-              + " rootWasReset=" + rootWasReset);
-        pw.println(prefix + "affinity=" + affinity);
-        pw.println(prefix + "intent=" + intent);
-        pw.println(prefix + "affinityIntent=" + affinityIntent);
-        pw.println(prefix + "origActivity=" + origActivity);
-        pw.println(prefix + "lastActiveTime=" + lastActiveTime
-                +" (inactive for " + (getInactiveDuration()/1000) + "s)");
+        if (clearOnBackground || numActivities != 0 || rootWasReset) {
+            pw.print(prefix); pw.print("clearOnBackground="); pw.print(clearOnBackground);
+                    pw.print(" numActivities="); pw.print(numActivities);
+                    pw.print(" rootWasReset="); pw.println(rootWasReset);
+        }
+        if (affinity != null) {
+            pw.print(prefix); pw.print("affinity="); pw.println(affinity);
+        }
+        if (intent != null) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append(prefix); sb.append("intent={");
+            intent.toShortString(sb, true, false);
+            sb.append('}');
+            pw.println(sb.toString());
+        }
+        if (affinityIntent != null) {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append(prefix); sb.append("affinityIntent={");
+            affinityIntent.toShortString(sb, true, false);
+            sb.append('}');
+            pw.println(sb.toString());
+        }
+        if (origActivity != null) {
+            pw.print(prefix); pw.print("origActivity=");
+            pw.println(origActivity.flattenToShortString());
+        }
+        if (realActivity != null) {
+            pw.print(prefix); pw.print("realActivity=");
+            pw.println(realActivity.flattenToShortString());
+        }
+        pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
+                pw.print(" (inactive for ");
+                pw.print((getInactiveDuration()/1000)); pw.println("s)");
     }
 
     public String toString() {
-        return "Task{" + taskId + " "
-                + (affinity != null ? affinity
-                        : (intent != null ? intent.getComponent().flattenToShortString()
-                                : affinityIntent != null ? affinityIntent.getComponent().flattenToShortString() : "??"))
-                + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("TaskRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" #");
+        sb.append(taskId);
+        if (affinity != null) {
+            sb.append(" A ");
+            sb.append(affinity);
+        } else if (intent != null) {
+            sb.append(" I ");
+            sb.append(intent.getComponent().flattenToShortString());
+        } else if (affinityIntent != null) {
+            sb.append(" aI ");
+            sb.append(affinityIntent.getComponent().flattenToShortString());
+        } else {
+            sb.append(" ??");
+        }
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index fb7a745..ffa8a2a 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -30,6 +30,8 @@
     final HashSet<HistoryRecord> readActivities = new HashSet<HistoryRecord>();
     final HashSet<HistoryRecord> writeActivities = new HashSet<HistoryRecord>();
     
+    String stringName;
+    
     UriPermission(int _uid, Uri _uri) {
         uid = _uid;
         uri = _uri;
@@ -65,18 +67,29 @@
     }
     
     public String toString() {
-        return "UriPermission{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " " + uri + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("UriPermission{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(uri);
+        sb.append('}');
+        return stringName = sb.toString();
     }
 
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "  modeFlags=0x" + Integer.toHexString(modeFlags)
-                + " uid=" + uid 
-                + " globalModeFlags=0x"
-                + Integer.toHexString(globalModeFlags));
-        pw.println(prefix + "  readActivities=" + readActivities);
-        pw.println(prefix + "  writeActivities=" + writeActivities);
+        pw.print(prefix); pw.print("modeFlags=0x");
+                pw.print(Integer.toHexString(modeFlags));
+                pw.print(" uid="); pw.print(uid); 
+                pw.print(" globalModeFlags=0x");
+                pw.println(Integer.toHexString(globalModeFlags));
+        if (readActivities.size() != 0) {
+            pw.print(prefix); pw.print("readActivities="); pw.println(readActivities);
+        }
+        if (writeActivities.size() != 0) {
+            pw.print(prefix); pw.print("writeActivities="); pw.println(writeActivities);
+        }
     }
 }
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 3922f39..b6f9158 100755
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -37,11 +37,11 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TimeZone;
 
 /**
  * This service collects the statistics associated with usage
@@ -53,6 +53,23 @@
     public static final String SERVICE_NAME = "usagestats";
     private static final boolean localLOGV = false;
     private static final String TAG = "UsageStats";
+    
+    // Current on-disk Parcel version
+    private static final int VERSION = 1004;
+
+    private static final int CHECKIN_VERSION = 3;
+    
+    private static final String FILE_PREFIX = "usage-";
+    
+    private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms
+    
+    private static final int MAX_NUM_FILES = 5;
+    
+    private static final int NUM_LAUNCH_TIME_BINS = 10;
+    private static final int[] LAUNCH_TIME_BINS = {
+        250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000
+    };
+    
     static IUsageStats sService;
     private Context mContext;
     // structure used to maintain statistics since the last checkin.
@@ -66,16 +83,48 @@
     // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
     private String mResumedPkg;
     private File mFile;
+    private String mFileLeaf;
     //private File mBackupFile;
-    private long mLastWriteRealTime;
-    private int _FILE_WRITE_INTERVAL = 30*60*1000; //ms
-    private static final String _PREFIX_DELIMIT=".";
-    private String mFilePrefix;
+    private long mLastWriteElapsedTime;
+    private File mDir;
     private Calendar mCal;
-    private static final int  _MAX_NUM_FILES = 10;
-    private long mLastTime;
+    private int mLastWriteDay;
+    
+    static class TimeStats {
+        int[] times = new int[NUM_LAUNCH_TIME_BINS];
+        
+        TimeStats() {
+        }
+        
+        void add(int val) {
+            final int[] bins = LAUNCH_TIME_BINS;
+            for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
+                if (val < bins[i]) {
+                    times[i]++;
+                    return;
+                }
+            }
+            times[NUM_LAUNCH_TIME_BINS-1]++;
+        }
+        
+        TimeStats(Parcel in) {
+            final int[] localTimes = times;
+            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+                localTimes[i] = in.readInt();
+            }
+        }
+        
+        void writeToParcel(Parcel out) {
+            final int[] localTimes = times;
+            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+                out.writeInt(localTimes[i]);
+            }
+        }
+    }
     
     private class PkgUsageStatsExtended {
+        final HashMap<String, TimeStats> mLaunchTimes
+                = new HashMap<String, TimeStats>();
         int mLaunchCount;
         long mUsageTime;
         long mPausedTime;
@@ -85,44 +134,106 @@
             mLaunchCount = 0;
             mUsageTime = 0;
         }
+        
+        PkgUsageStatsExtended(Parcel in) {
+            mLaunchCount = in.readInt();
+            mUsageTime = in.readLong();
+            if (localLOGV) Log.v(TAG, "Launch count: " + mLaunchCount
+                    + ", Usage time:" + mUsageTime);
+            
+            final int N = in.readInt();
+            if (localLOGV) Log.v(TAG, "Reading comps: " + N);
+            for (int i=0; i<N; i++) {
+                String comp = in.readString();
+                if (localLOGV) Log.v(TAG, "Component: " + comp);
+                TimeStats times = new TimeStats(in);
+                mLaunchTimes.put(comp, times);
+            }
+        }
+        
         void updateResume() {
             mLaunchCount ++;
             mResumedTime = SystemClock.elapsedRealtime();
         }
+        
         void updatePause() {
             mPausedTime =  SystemClock.elapsedRealtime();
             mUsageTime += (mPausedTime - mResumedTime);
         }
+        
+        void addLaunchTime(String comp, int millis) {
+            TimeStats times = mLaunchTimes.get(comp);
+            if (times == null) {
+                times = new TimeStats();
+                mLaunchTimes.put(comp, times);
+            }
+            times.add(millis);
+        }
+        
+        void writeToParcel(Parcel out) {
+            out.writeInt(mLaunchCount);
+            out.writeLong(mUsageTime);
+            final int N = mLaunchTimes.size();
+            out.writeInt(N);
+            if (N > 0) {
+                for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
+                    out.writeString(ent.getKey());
+                    TimeStats times = ent.getValue();
+                    times.writeToParcel(out);
+                }
+            }
+        }
+        
         void clear() {
+            mLaunchTimes.clear();
             mLaunchCount = 0;
             mUsageTime = 0;
         }
     }
     
-    UsageStatsService(String fileName) {
+    UsageStatsService(String dir) {
         mStats = new HashMap<String, PkgUsageStatsExtended>();
         mStatsLock = new Object();
         mFileLock = new Object();
-        mFilePrefix = fileName;
-        mCal = Calendar.getInstance();
+        mDir = new File(dir);
+        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
+        
+        mDir.mkdir();
+        
+        // Remove any old usage files from previous versions.
+        File parentDir = mDir.getParentFile();
+        String fList[] = parentDir.list();
+        if (fList != null) {
+            String prefix = mDir.getName() + ".";
+            int i = fList.length;
+            while (i > 0) {
+                i--;
+                if (fList[i].startsWith(prefix)) {
+                    Log.i(TAG, "Deleting old usage file: " + fList[i]);
+                    (new File(parentDir, fList[i])).delete();
+                }
+            }
+        }
+        
         // Update current stats which are binned by date
-        String uFileName = getCurrentDateStr(mFilePrefix);
-        mFile = new File(uFileName);
+        mFileLeaf = getCurrentDateStr(FILE_PREFIX);
+        mFile = new File(mDir, mFileLeaf);
         readStatsFromFile();
-        mLastWriteRealTime = SystemClock.elapsedRealtime();
-        mLastTime = new Date().getTime();
+        mLastWriteElapsedTime = SystemClock.elapsedRealtime();
+        // mCal was set by getCurrentDateStr(), want to use that same time.
+        mLastWriteDay = mCal.get(Calendar.DAY_OF_YEAR);
     }
 
     /*
      * Utility method to convert date into string.
      */
     private String getCurrentDateStr(String prefix) {
-        mCal.setTime(new Date());
+        mCal.setTimeInMillis(System.currentTimeMillis());
         StringBuilder sb = new StringBuilder();
         if (prefix != null) {
             sb.append(prefix);
-            sb.append(".");
         }
+        sb.append(mCal.get(Calendar.YEAR));
         int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
         if (mm < 10) {
             sb.append("0");
@@ -133,7 +244,6 @@
             sb.append("0");
         }
         sb.append(dd);
-        sb.append(mCal.get(Calendar.YEAR));
         return sb.toString();
     }
     
@@ -166,11 +276,20 @@
     
     private void readStatsFLOCK(File file) throws IOException {
         Parcel in = getParcelForFile(file);
-        while (in.dataAvail() > 0) {
+        int vers = in.readInt();
+        if (vers != VERSION) {
+            Log.w(TAG, "Usage stats version changed; dropping");
+            return;
+        }
+        int N = in.readInt();
+        while (N > 0) {
+            N--;
             String pkgName = in.readString();
-            PkgUsageStatsExtended pus = new PkgUsageStatsExtended();
-            pus.mLaunchCount = in.readInt();
-            pus.mUsageTime = in.readLong();
+            if (pkgName == null) {
+                break;
+            }
+            if (localLOGV) Log.v(TAG, "Reading package #" + N + ": " + pkgName);
+            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
             synchronized (mStatsLock) {
                 mStats.put(pkgName, pus);
             }
@@ -178,27 +297,18 @@
     }
 
     private ArrayList<String> getUsageStatsFileListFLOCK() {
-        File dir = getUsageFilesDir();
-        if (dir == null) {
-            Log.w(TAG, "Couldnt find writable directory for usage stats file");
-            return null;
-        }
         // Check if there are too many files in the system and delete older files
-        String fList[] = dir.list();
+        String fList[] = mDir.list();
         if (fList == null) {
             return null;
         }
-        File pre = new File(mFilePrefix);
-        String filePrefix = pre.getName();
-        // file name followed by dot
-        int prefixLen = filePrefix.length()+1;
         ArrayList<String> fileList = new ArrayList<String>();
         for (String file : fList) {
-            int index = file.indexOf(filePrefix);
-            if (index == -1) {
+            if (!file.startsWith(FILE_PREFIX)) {
                 continue;
             }
             if (file.endsWith(".bak")) {
+                (new File(mDir, file)).delete();
                 continue;
             }
             fileList.add(file);
@@ -206,20 +316,7 @@
         return fileList;
     }
     
-    private File getUsageFilesDir() {
-        if (mFilePrefix == null) {
-            return null;
-        }
-        File pre = new File(mFilePrefix);
-        return new File(pre.getParent());
-    }
-    
     private void checkFileLimitFLOCK() {
-        File dir = getUsageFilesDir();
-        if (dir == null) {
-            Log.w(TAG, "Couldnt find writable directory for usage stats file");
-            return;
-        }
         // Get all usage stats output files
         ArrayList<String> fileList = getUsageStatsFileListFLOCK();
         if (fileList == null) {
@@ -227,49 +324,54 @@
             return;
         }
         int count = fileList.size();
-        if (count <= _MAX_NUM_FILES) {
+        if (count <= MAX_NUM_FILES) {
             return;
         }
         // Sort files
         Collections.sort(fileList);
-        count -= _MAX_NUM_FILES;
+        count -= MAX_NUM_FILES;
         // Delete older files
         for (int i = 0; i < count; i++) {
             String fileName = fileList.get(i);
-            File file = new File(dir, fileName);
-            Log.i(TAG, "Deleting file : "+fileName);
+            File file = new File(mDir, fileName);
+            Log.i(TAG, "Deleting usage file : " + fileName);
             file.delete();
         }
     }
     
-    private void writeStatsToFile() {
+    private void writeStatsToFile(boolean force) {
         synchronized (mFileLock) {
-            long currTime = new Date().getTime();
-            boolean dayChanged =  ((currTime - mLastTime) >= (24*60*60*1000));
-            long currRealTime = SystemClock.elapsedRealtime();
-            if (((currRealTime-mLastWriteRealTime) < _FILE_WRITE_INTERVAL) &&
-                    (!dayChanged)) {
-                // wait till the next update
-                return;
+            mCal.setTimeInMillis(System.currentTimeMillis());
+            final int curDay = mCal.get(Calendar.DAY_OF_YEAR);
+            // Determine if the day changed...  note that this will be wrong
+            // if the year has changed but we are in the same day of year...
+            // we can probably live with this.
+            final boolean dayChanged =  curDay != mLastWriteDay;
+            long currElapsedTime = SystemClock.elapsedRealtime();
+            if (!force) {
+                if (((currElapsedTime-mLastWriteElapsedTime) < FILE_WRITE_INTERVAL) &&
+                        (!dayChanged)) {
+                    // wait till the next update
+                    return;
+                }
             }
             // Get the most recent file
-            String todayStr = getCurrentDateStr(mFilePrefix);
+            mFileLeaf = getCurrentDateStr(FILE_PREFIX);
             // Copy current file to back up
             File backupFile =  new File(mFile.getPath() + ".bak");
             mFile.renameTo(backupFile);
             try {
-                checkFileLimitFLOCK();
-                mFile.createNewFile();
                 // Write mStats to file
                 writeStatsFLOCK();
-                mLastWriteRealTime = currRealTime;
-                mLastTime = currTime;
+                mLastWriteElapsedTime = currElapsedTime;
                 if (dayChanged) {
+                    mLastWriteDay = curDay;
                     // clear stats
                     synchronized (mStats) {
                         mStats.clear();
                     }
-                    mFile = new File(todayStr);
+                    mFile = new File(mDir, mFileLeaf);
+                    checkFileLimitFLOCK();
                 }
                 // Delete the backup file
                 if (backupFile != null) {
@@ -278,6 +380,7 @@
             } catch (IOException e) {
                 Log.w(TAG, "Failed writing stats to file:" + mFile);
                 if (backupFile != null) {
+                    mFile.delete();
                     backupFile.renameTo(mFile);
                 }
             }
@@ -286,22 +389,26 @@
 
     private void writeStatsFLOCK() throws IOException {
         FileOutputStream stream = new FileOutputStream(mFile);
-        Parcel out = Parcel.obtain();
-        writeStatsToParcelFLOCK(out);
-        stream.write(out.marshall());
-        out.recycle();
-        stream.flush();
-        stream.close();
+        try {
+            Parcel out = Parcel.obtain();
+            writeStatsToParcelFLOCK(out);
+            stream.write(out.marshall());
+            out.recycle();
+            stream.flush();
+        } finally {
+            stream.close();
+        }
     }
 
     private void writeStatsToParcelFLOCK(Parcel out) {
         synchronized (mStatsLock) {
+            out.writeInt(VERSION);
             Set<String> keys = mStats.keySet();
+            out.writeInt(keys.size());
             for (String key : keys) {
                 PkgUsageStatsExtended pus = mStats.get(key);
                 out.writeString(key);
-                out.writeInt(pus.mLaunchCount);
-                out.writeLong(pus.mUsageTime);
+                pus.writeToParcel(out);
             }
         }
     }
@@ -355,6 +462,10 @@
             return;
         }
         if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
+        
+        // Persist current data to file if needed.
+        writeStatsToFile(false);
+        
         synchronized (mStatsLock) {
             PkgUsageStatsExtended pus = mStats.get(pkgName);
             if (pus == null) {
@@ -364,8 +475,25 @@
             }
             pus.updatePause();
         }
-        // Persist data to file
-        writeStatsToFile();
+    }
+    
+    public void noteLaunchTime(ComponentName componentName, int millis) {
+        enforceCallingPermission();
+        String pkgName;
+        if ((componentName == null) ||
+                ((pkgName = componentName.getPackageName()) == null)) {
+            return;
+        }
+        
+        // Persist current data to file if needed.
+        writeStatsToFile(false);
+        
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus != null) {
+                pus.addLaunchTime(componentName.getClassName(), millis);
+            }
+        }
     }
     
     public void enforceCallingPermission() {
@@ -432,27 +560,25 @@
         }
     }
     
-    private void collectDumpInfoFLOCK(PrintWriter pw, String[] args) {
+    private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput,
+            boolean deleteAfterPrint) {
         List<String> fileList = getUsageStatsFileListFLOCK();
         if (fileList == null) {
             return;
         }
-        final boolean isCheckinRequest = scanArgs(args, "-c");
         Collections.sort(fileList);
-        File usageFile = new File(mFilePrefix);
-        String dirName = usageFile.getParent();
-        File dir = new File(dirName);
-        String filePrefix = usageFile.getName();
-        // file name followed by dot
-        int prefixLen = filePrefix.length()+1;
-        String todayStr = getCurrentDateStr(null);
         for (String file : fileList) {
-            File dFile = new File(dir, file);
-            String dateStr = file.substring(prefixLen);
+            if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) {
+                // In this mode we don't print the current day's stats, since
+                // they are incomplete.
+                continue;
+            }
+            File dFile = new File(mDir, file);
+            String dateStr = file.substring(FILE_PREFIX.length());
             try {
                 Parcel in = getParcelForFile(dFile);
-                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCheckinRequest);
-                if (isCheckinRequest && !todayStr.equalsIgnoreCase(dateStr)) {
+                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput);
+                if (deleteAfterPrint) {
                     // Delete old file after collecting info only for checkin requests
                     dFile.delete();
                 }
@@ -466,40 +592,101 @@
     }
     
     private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
-            String date, boolean isCheckinRequest) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Date:");
-        sb.append(date);
-        boolean first = true;
-        while (in.dataAvail() > 0) {
-            String pkgName = in.readString();
-            int launchCount = in.readInt();
-            long usageTime = in.readLong();
-            if (isCheckinRequest) {
-                if (!first) {
-                    sb.append(",");
-                }
-                sb.append(pkgName);
-                sb.append(",");
-                sb.append(launchCount);
-                sb.append(",");
-                sb.append(usageTime);
-                sb.append("ms");
-            } else {
-                if (first) {
-                    sb.append("\n");
-                }
-                sb.append("pkg=");
-                sb.append(pkgName);
-                sb.append(", launchCount=");
-                sb.append(launchCount);
-                sb.append(", usageTime=");
-                sb.append(usageTime);
-                sb.append(" ms\n");
-            }
-            first = false;
+            String date, boolean isCompactOutput) {
+        StringBuilder sb = new StringBuilder(512);
+        if (isCompactOutput) {
+            sb.append("D:");
+            sb.append(CHECKIN_VERSION);
+            sb.append(',');
+        } else {
+            sb.append("Date: ");
         }
-        pw.write(sb.toString());
+        
+        sb.append(date);
+        
+        int vers = in.readInt();
+        if (vers != VERSION) {
+            sb.append(" (old data version)");
+            pw.println(sb.toString());
+            return;
+        }
+        
+        pw.println(sb.toString());
+        int N = in.readInt();
+        
+        while (N > 0) {
+            N--;
+            String pkgName = in.readString();
+            if (pkgName == null) {
+                break;
+            }
+            sb.setLength(0);
+            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
+            if (isCompactOutput) {
+                sb.append("P:");
+                sb.append(pkgName);
+                sb.append(",");
+                sb.append(pus.mLaunchCount);
+                sb.append(",");
+                sb.append(pus.mUsageTime);
+                sb.append('\n');
+                final int NC = pus.mLaunchTimes.size();
+                if (NC > 0) {
+                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
+                        sb.append("A:");
+                        sb.append(ent.getKey());
+                        TimeStats times = ent.getValue();
+                        for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+                            sb.append(",");
+                            sb.append(times.times[i]);
+                        }
+                        sb.append('\n');
+                    }
+                }
+                
+            } else {
+                sb.append("  ");
+                sb.append(pkgName);
+                sb.append(": ");
+                sb.append(pus.mLaunchCount);
+                sb.append(" times, ");
+                sb.append(pus.mUsageTime);
+                sb.append(" ms");
+                sb.append('\n');
+                final int NC = pus.mLaunchTimes.size();
+                if (NC > 0) {
+                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
+                        sb.append("    ");
+                        sb.append(ent.getKey());
+                        TimeStats times = ent.getValue();
+                        int lastBin = 0;
+                        boolean first = true;
+                        for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
+                            if (times.times[i] != 0) {
+                                sb.append(first ? ": " : ", ");
+                                sb.append(lastBin);
+                                sb.append('-');
+                                sb.append(LAUNCH_TIME_BINS[i]);
+                                sb.append('=');
+                                sb.append(times.times[i]);
+                                first = false;
+                            }
+                            lastBin = LAUNCH_TIME_BINS[i];
+                        }
+                        if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
+                            sb.append(first ? ": " : ", ");
+                            sb.append(">=");
+                            sb.append(lastBin);
+                            sb.append('=');
+                            sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
+                        }
+                        sb.append('\n');
+                    }
+                }
+            }
+            
+            pw.write(sb.toString());
+        }
     }
     
     /**
@@ -524,8 +711,19 @@
      * The data persisted to file is parsed and the stats are computed. 
      */
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        final boolean isCheckinRequest = scanArgs(args, "--checkin");
+        final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c");
+        final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d");
+        
+        // Make sure the current stats are written to the file.  This
+        // doesn't need to be done if we are deleting files after printing,
+        // since it that case we won't print the current stats.
+        if (!deleteAfterPrint) {
+            writeStatsToFile(true);
+        }
+        
         synchronized (mFileLock) {
-            collectDumpInfoFLOCK(pw, args);
+            collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint);
         }
     }
 
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 713cd13..0b161d6 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -16,13 +16,6 @@
 
 package com.android.server.status;
 
-import com.android.internal.R;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.GpsLocationProvider;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.server.am.BatteryStatsService;
-
 import android.app.AlertDialog;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
@@ -59,6 +52,14 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.R;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.location.GpsLocationProvider;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.cdma.TtyIntent;
+import com.android.server.am.BatteryStatsService;
+
 import java.util.Calendar;
 import java.util.TimeZone;
 
@@ -110,7 +111,10 @@
     // phone
     private TelephonyManager mPhone;
     private IBinder mPhoneIcon;
+
+    //***** Signal strength icons
     private IconData mPhoneData;
+    //GSM/UMTS
     private static final int[] sSignalImages = new int[] {
             com.android.internal.R.drawable.stat_sys_signal_0,
             com.android.internal.R.drawable.stat_sys_signal_1,
@@ -125,7 +129,32 @@
             com.android.internal.R.drawable.stat_sys_r_signal_3,
             com.android.internal.R.drawable.stat_sys_r_signal_4
         };
+    //CDMA
+    private static final int[] sSignalImages_cdma = new int[] {
+        com.android.internal.R.drawable.stat_sys_signal_0_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_1_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_2_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_3_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_4_cdma
+    };
+    private static final int[] sSignalImages_r_cdma = new int[] {
+        com.android.internal.R.drawable.stat_sys_r_signal_0_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_1_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_2_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_3_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_4_cdma
+    };
+    private static final int[] sSignalImages_ra_cdma = new int[] {
+        com.android.internal.R.drawable.stat_sys_ra_signal_0_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_1_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_2_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_3_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_4_cdma
+    };
+
+    //***** Data connection icons
     private int[] mDataIconList = sDataNetType_g;
+    //GSM/UMTS
     private static final int[] sDataNetType_g = new int[] {
             com.android.internal.R.drawable.stat_sys_data_connected_g,
             com.android.internal.R.drawable.stat_sys_data_in_g,
@@ -144,12 +173,25 @@
             com.android.internal.R.drawable.stat_sys_data_out_e,
             com.android.internal.R.drawable.stat_sys_data_inandout_e,
         };
+    //CDMA
+    private static final int[] sDataNetType_evdo = new int[] {
+        com.android.internal.R.drawable.stat_sys_data_connected_evdo,
+        com.android.internal.R.drawable.stat_sys_data_in_evdo,
+        com.android.internal.R.drawable.stat_sys_data_out_evdo,
+        com.android.internal.R.drawable.stat_sys_data_inandout_evdo,
+    };
+    private static final int[] sDataNetType_1xrtt = new int[] {
+        com.android.internal.R.drawable.stat_sys_data_connected_1xrtt,
+        com.android.internal.R.drawable.stat_sys_data_in_1xrtt,
+        com.android.internal.R.drawable.stat_sys_data_out_1xrtt,
+        com.android.internal.R.drawable.stat_sys_data_inandout_1xrtt,
+    };
+
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
-    SimCard.State mSimState = SimCard.State.READY;
+    IccCard.State mSimState = IccCard.State.READY;
     int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
     int mDataState = TelephonyManager.DATA_DISCONNECTED;
-    int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
     int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
     ServiceState mServiceState;
     int mSignalAsu = -1;
@@ -163,7 +205,7 @@
     private IBinder mVolumeIcon;
     private IconData mVolumeData;
     private boolean mVolumeVisible;
-    
+
     // bluetooth device status
     private IBinder mBluetoothIcon;
     private IconData mBluetoothData;
@@ -202,6 +244,11 @@
     private IBinder mSyncActiveIcon;
     private IBinder mSyncFailingIcon;
 
+    // TTY mode
+    // Icon lit when TTY mode is enabled
+    private IBinder mTTYModeIcon;
+    private IconData mTTYModeEnableIconData;
+
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -250,6 +297,9 @@
             else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
                 updateSimState(intent);
             }
+            else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
+                updateTTY(intent);
+            }
         }
     };
 
@@ -294,7 +344,13 @@
         mWifiIcon = service.addIcon(mWifiData, null);
         service.setIconVisibility(mWifiIcon, false);
         // wifi will get updated by the sticky intents
-        
+
+        // TTY status
+        mTTYModeEnableIconData = IconData.makeIcon("tty",
+                null, com.android.internal.R.drawable.stat_sys_tty_mode, 0, 0);
+        mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
+        service.setIconVisibility(mTTYModeIcon, false);
+
         // bluetooth status
         mBluetoothData = IconData.makeIcon("bluetooth",
                 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
@@ -362,6 +418,7 @@
         filter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
         filter.addAction(GpsLocationProvider.GPS_FIX_CHANGE_ACTION);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
     }
 
@@ -506,7 +563,7 @@
                 com.android.internal.R.styleable.Theme);
         lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
         a.recycle();
-        
+
         lp.setTitle("Battery");
 
         TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
@@ -642,26 +699,26 @@
     
 
     private final void updateSimState(Intent intent) {
-        String stateExtra = intent.getStringExtra(SimCard.INTENT_KEY_SIM_STATE);
-        if (SimCard.INTENT_VALUE_SIM_ABSENT.equals(stateExtra)) {
-            mSimState = SimCard.State.ABSENT;
+        String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
+        if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+            mSimState = IccCard.State.ABSENT;
         }
-        else if (SimCard.INTENT_VALUE_SIM_READY.equals(stateExtra)) {
-            mSimState = SimCard.State.READY;
+        else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+            mSimState = IccCard.State.READY;
         }
-        else if (SimCard.INTENT_VALUE_SIM_LOCKED.equals(stateExtra)) {
-            final String lockedReason = intent.getStringExtra(SimCard.INTENT_KEY_LOCKED_REASON);
-            if (SimCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
-                mSimState = SimCard.State.PIN_REQUIRED;
+        else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+            final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
+            if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                mSimState = IccCard.State.PIN_REQUIRED;
             } 
-            else if (SimCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
-                mSimState = SimCard.State.PUK_REQUIRED;
+            else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                mSimState = IccCard.State.PUK_REQUIRED;
             }
             else {
-                mSimState = SimCard.State.NETWORK_LOCKED;
+                mSimState = IccCard.State.NETWORK_LOCKED;
             }
         } else {
-            mSimState = SimCard.State.UNKNOWN;
+            mSimState = IccCard.State.UNKNOWN;
         }
         updateDataIcon();
     }
@@ -707,28 +764,54 @@
         else asu = 1;
 
         int[] iconList;
-        if (mPhone.isNetworkRoaming()) {
+        if (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+            switch(ss.getExtendedCdmaRoaming()) {
+            case ServiceState.REGISTRATION_STATE_ROAMING:
+                iconList = this.sSignalImages_r_cdma;
+                break;
+            case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
+                iconList = this.sSignalImages_ra_cdma;
+                break;
+            default:
+                iconList = this.sSignalImages_cdma;
+            break;
+            }
+        } else if (mPhone.isNetworkRoaming()) {
             iconList = sSignalImages_r;
         } else {
             iconList = sSignalImages;
         }
-        
+
         mPhoneData.iconId = iconList[asu];
         mService.updateIcon(mPhoneIcon, mPhoneData, null);
     }
 
     private final void updateDataNetType() {
-        mDataNetType = mPhone.getNetworkType();
-        switch (mDataNetType) {
-            case TelephonyManager.NETWORK_TYPE_EDGE:
-                mDataIconList = sDataNetType_e;
-                break;
-            case TelephonyManager.NETWORK_TYPE_UMTS:
-                mDataIconList = sDataNetType_3g;
-                break;
-            default:
-                mDataIconList = sDataNetType_g;
-                break;
+        int net = mPhone.getNetworkType();
+        ServiceState ss = this.mServiceState;
+
+        switch (net) {
+
+        case TelephonyManager.NETWORK_TYPE_EDGE:
+            mDataIconList = sDataNetType_e;
+            break;
+        case TelephonyManager.NETWORK_TYPE_UMTS:
+            mDataIconList = sDataNetType_3g;
+            break;
+        case TelephonyManager.NETWORK_TYPE_CDMA:
+            // display 1xRTT for IS95A/B
+            mDataIconList = this.sDataNetType_1xrtt;
+            break;
+        case TelephonyManager.NETWORK_TYPE_1xRTT:
+            mDataIconList = this.sDataNetType_1xrtt;
+            break;
+        case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
+        case TelephonyManager.NETWORK_TYPE_EVDO_A:
+            mDataIconList = sDataNetType_evdo;
+            break;
+        default:
+            mDataIconList = sDataNetType_g;
+        break;
         }
     }
 
@@ -736,9 +819,9 @@
         int iconId;
         boolean visible = true;
 
-        if (mSimState == SimCard.State.READY || mSimState == SimCard.State.UNKNOWN) {
+        if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
             int data = mDataState;
-            
+
             int[] list = mDataIconList;
 
             ServiceState ss = mServiceState;
@@ -775,7 +858,7 @@
         }
         long ident = Binder.clearCallingIdentity();
         try {
-            mBatteryStats.notePhoneDataConnectionState(mDataNetType, visible);
+            mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
         } catch (RemoteException e) {
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -865,10 +948,10 @@
                 } else {
                     iconId = sWifiSignalImages[mLastWifiSignalLevel];
                 }
-                
+
                 // Show the icon since wi-fi is connected
                 mService.setIconVisibility(mWifiIcon, true);
-                
+
             } else {
                 mLastWifiSignalLevel = -1;
                 mIsWifiConnected = false;
@@ -914,6 +997,24 @@
         }
     }
 
+    private final void updateTTY(Intent intent) {       
+        final String action = intent.getAction();
+        final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
+
+        Log.i(TAG, "updateTTY: enabled: " + enabled);
+
+        if (enabled) {
+            // TTY is on
+            Log.i(TAG, "updateTTY: set TTY on");
+            mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
+            mService.setIconVisibility(mTTYModeIcon, true);          
+        } else {
+            // TTY is off
+            Log.i(TAG, "updateTTY: set TTY off");
+            mService.setIconVisibility(mTTYModeIcon, false);           
+        }
+    }
+
     private class StatusBarHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
@@ -927,3 +1028,6 @@
         }
     }
 }
+
+
+
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index 464085f..bb5f126 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -19,8 +19,14 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.provider.Settings;
+
+
+import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.RILConstants;
 
 /**
  * Abstract class that represents the location of the device.  Currently the only
@@ -56,7 +62,17 @@
      * @hide
      */
     public static CellLocation newFromBundle(Bundle bundle) {
-        return new GsmCellLocation(bundle);
+        // TODO: My need to be use: Settings.Secure.getInt(mContext, Settings.Secure.CURRENT_ACTIVE_PHONE, 0))
+        //       instead of SystemProperties???
+
+        // NOTE here TelephonyManager.getDefault().getPhoneType() cannot be used since at startup
+        //      ITelephony have not been created
+        if (RILConstants.CDMA_PHONE ==
+                SystemProperties.getInt(Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.GSM_PHONE)) {
+            return new CdmaCellLocation(bundle);
+        } else {
+            return new GsmCellLocation(bundle);
+        }
     }
 
     /**
@@ -66,8 +82,20 @@
 
     /**
      * Return a new CellLocation object representing an unknown location.
+     *
      */
     public static CellLocation getEmpty() {
-        return new GsmCellLocation();
+        // TODO: My need to be use: Settings.Secure.getInt(mContext, Settings.Secure.CURRENT_ACTIVE_PHONE, 0))
+        //       instead of SystemProperties???
+
+        // NOTE here TelephonyManager.getDefault().getPhoneType() cannot be used since at startup
+        //      ITelephony have not been created
+        if (RILConstants.CDMA_PHONE ==
+                SystemProperties.getInt(Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.GSM_PHONE)) {
+            return new CdmaCellLocation();
+        } else {
+            return new GsmCellLocation();
+        }
     }
+
 }
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index 0bc6c04..8a47339 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -25,7 +25,7 @@
 
 /**
  * Watches a {@link TextView} and if a phone number is entered will format it using
- * {@link PhoneNumberUtils#formatNumber(Editable, int)}. The formatting is based on 
+ * {@link PhoneNumberUtils#formatNumber(Editable, int)}. The formatting is based on
  * the current system locale when this object is created and future locale changes
  * may not take effect on this instance.
  */
@@ -35,7 +35,7 @@
     static private Locale sCachedLocale;
     private boolean mFormatting;
     private boolean mDeletingHyphen;
-    private int mHyphenStart;    
+    private int mHyphenStart;
     private boolean mDeletingBackward;
 
     public PhoneNumberFormattingTextWatcher() {
@@ -60,7 +60,7 @@
                     text.delete(mHyphenStart, mHyphenStart + 1);
                 }
             }
-            
+
             PhoneNumberUtils.formatNumber(text, sFormatType);
 
             mFormatting = false;
@@ -73,8 +73,8 @@
             // Make sure user is deleting one char, without a selection
             final int selStart = Selection.getSelectionStart(s);
             final int selEnd = Selection.getSelectionEnd(s);
-            if (s.length() > 1 // Can delete another character 
-                    && count == 1 // Deleting only one character 
+            if (s.length() > 1 // Can delete another character
+                    && count == 1 // Deleting only one character
                     && after == 0 // Deleting
                     && s.charAt(start) == '-' // a hyphen
                     && selStart == selEnd) { // no selection
@@ -89,7 +89,7 @@
             } else {
                 mDeletingHyphen = false;
             }
-        }        
+        }
     }
 
     public void onTextChanged(CharSequence s, int start, int before, int count) {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 8a8a675..df6860b 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -11,18 +11,18 @@
 
 /**
  * A listener class for monitoring changes in specific telephony states
- * on the device, including service state, signal strength, message 
+ * on the device, including service state, signal strength, message
  * waiting indicator (voicemail), and others.
  * <p>
- * Override the methods for the state that you wish to receive updates for, and 
+ * Override the methods for the state that you wish to receive updates for, and
  * pass your PhoneStateListener object, along with bitwise-or of the LISTEN_
  * flags to {@link TelephonyManager#listen TelephonyManager.listen()}.
  * <p>
  * Note that access to some telephony information is
- * permission-protected. Your application won't receive updates for protected 
- * information unless it has the appropriate permissions declared in 
+ * permission-protected. Your application won't receive updates for protected
+ * information unless it has the appropriate permissions declared in
  * its manifest file. Where permissions apply, they are noted in the
- * appropriate LISTEN_ flags. 
+ * appropriate LISTEN_ flags.
  */
 public class PhoneStateListener {
 
@@ -67,17 +67,17 @@
     public static final int LISTEN_CALL_FORWARDING_INDICATOR                = 0x00000008;
 
     /**
-     * Listen for changes to the device's cell location. Note that 
+     * Listen for changes to the device's cell location. Note that
      * this will result in frequent callbacks to the listener.
      * {@more}
      * Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION
      * ACCESS_COARSE_LOCATION}
      * <p>
-     * If you need regular location updates but want more control over 
-     * the update interval or location precision, you can set up a listener 
-     * through the {@link android.location.LocationManager location manager} 
-     * instead. 
-     * 
+     * If you need regular location updates but want more control over
+     * the update interval or location precision, you can set up a listener
+     * through the {@link android.location.LocationManager location manager}
+     * instead.
+     *
      * @see #onCellLocationChanged
      */
     public static final int LISTEN_CELL_LOCATION                            = 0x00000010;
@@ -100,7 +100,7 @@
      * Listen for changes to the direction of data traffic on the data
      * connection (cellular).
      *
-     * Example: The status bar uses this to display the appropriate  
+     * Example: The status bar uses this to display the appropriate
      * data-traffic icon.
      *
      * @see #onDataActivity
@@ -111,7 +111,7 @@
     }
 
     /**
-     * Callback invoked when device service state changes. 
+     * Callback invoked when device service state changes.
      *
      * @see ServiceState#STATE_EMERGENCY_ONLY
      * @see ServiceState#STATE_IN_SERVICE
@@ -135,28 +135,28 @@
     }
 
     /**
-     * Callback invoked when the message-waiting indicator changes. 
+     * Callback invoked when the message-waiting indicator changes.
      */
     public void onMessageWaitingIndicatorChanged(boolean mwi) {
         // default implementation empty
     }
 
     /**
-     * Callback invoked when the call-forwarding indicator changes. 
+     * Callback invoked when the call-forwarding indicator changes.
      */
     public void onCallForwardingIndicatorChanged(boolean cfi) {
         // default implementation empty
     }
 
     /**
-     * Callback invoked when device cell location changes. 
+     * Callback invoked when device cell location changes.
      */
     public void onCellLocationChanged(CellLocation location) {
         // default implementation empty
     }
 
     /**
-     * Callback invoked when device call state changes. 
+     * Callback invoked when device call state changes.
      *
      * @see TelephonyManager#CALL_STATE_IDLE
      * @see TelephonyManager#CALL_STATE_RINGING
@@ -167,7 +167,7 @@
     }
 
     /**
-     * Callback invoked when connection state changes. 
+     * Callback invoked when connection state changes.
      *
      * @see TelephonyManager#DATA_DISCONNECTED
      * @see TelephonyManager#DATA_CONNECTING
@@ -179,7 +179,7 @@
     }
 
     /**
-     * Callback invoked when data activity state changes. 
+     * Callback invoked when data activity state changes.
      *
      * @see TelephonyManager#DATA_ACTIVITY_NONE
      * @see TelephonyManager#DATA_ACTIVITY_IN
diff --git a/telephony/java/android/telephony/ServiceState.aidl b/telephony/java/android/telephony/ServiceState.aidl
index b1cf379..8522889 100644
--- a/telephony/java/android/telephony/ServiceState.aidl
+++ b/telephony/java/android/telephony/ServiceState.aidl
@@ -2,16 +2,16 @@
 **
 ** Copyright 2007, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 2c58051..4de0954 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,7 +19,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import com.android.internal.telephony.Phone;
+import android.util.Log;
 
 /**
  * Contains phone state and service related information.
@@ -35,6 +35,8 @@
  */
 public class ServiceState implements Parcelable {
 
+    static final String LOG_TAG = "PHONE";
+
     /**
      * Normal operation condition, the phone is registered
      * with an operator either in home network or in roaming.
@@ -59,13 +61,61 @@
      */
     public static final int STATE_POWER_OFF = 3;
 
+
+    /**
+     * Available radio technologies for GSM, UMTS and CDMA.
+     */
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_UNKNOWN = 0;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_GPRS = 1;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_EDGE = 2;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_UMTS = 3;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_IS95A = 4;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_IS95B = 5;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_1xRTT = 6;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_EVDO_0 = 7;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_EVDO_A = 8;
+
+    /**
+     * Available registration states for GSM, UMTS and CDMA.
+     */
+    /** @hide */
+    public static final int REGISTRATION_STATE_NOT_REGISTERED_AND_NOT_SEARCHING = 0;
+    /** @hide */
+    public static final int REGISTRATION_STATE_HOME_NETWORK = 1;
+    /** @hide */
+    public static final int REGISTRATION_STATE_NOT_REGISTERED_AND_SEARCHING = 2;
+    /** @hide */
+    public static final int REGISTRATION_STATE_REGISTRATION_DENIED = 3;
+    /** @hide */
+    public static final int REGISTRATION_STATE_UNKNOWN = 4;
+    /** @hide */
+    public static final int REGISTRATION_STATE_ROAMING = 5;
+    /** @hide */
+    public static final int REGISTRATION_STATE_ROAMING_AFFILIATE = 6;
+
     private int mState = STATE_OUT_OF_SERVICE;
     private boolean mRoaming;
+    private int mExtendedCdmaRoaming;
     private String mOperatorAlphaLong;
     private String mOperatorAlphaShort;
     private String mOperatorNumeric;
     private boolean mIsManualNetworkSelection;
 
+    //***** CDMA
+    private int mRadioTechnology;
+    private boolean mCssIndicator;
+    private int mNetworkId;
+    private int mSystemId;
+
     /**
      * Create a new ServiceState from a intent notifier Bundle
      *
@@ -105,6 +155,11 @@
         mOperatorAlphaShort = s.mOperatorAlphaShort;
         mOperatorNumeric = s.mOperatorNumeric;
         mIsManualNetworkSelection = s.mIsManualNetworkSelection;
+        mRadioTechnology = s.mRadioTechnology;
+        mCssIndicator = s.mCssIndicator;
+        mNetworkId = s.mNetworkId;
+        mSystemId = s.mSystemId;
+        mExtendedCdmaRoaming = s.mExtendedCdmaRoaming;
     }
 
     /**
@@ -117,6 +172,11 @@
         mOperatorAlphaShort = in.readString();
         mOperatorNumeric = in.readString();
         mIsManualNetworkSelection = in.readInt() != 0;
+        mRadioTechnology = in.readInt();
+        mCssIndicator = (in.readInt() != 0);
+        mNetworkId = in.readInt();
+        mSystemId = in.readInt();
+        mExtendedCdmaRoaming = in.readInt();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -126,6 +186,11 @@
         out.writeString(mOperatorAlphaShort);
         out.writeString(mOperatorNumeric);
         out.writeInt(mIsManualNetworkSelection ? 1 : 0);
+        out.writeInt(mRadioTechnology);
+        out.writeInt(mCssIndicator ? 1 : 0);
+        out.writeInt(mNetworkId);
+        out.writeInt(mSystemId);
+        out.writeInt(mExtendedCdmaRoaming);
     }
 
     public int describeContents() {
@@ -166,6 +231,11 @@
         return mRoaming;
     }
 
+    /** @hide */
+    public int getExtendedCdmaRoaming(){
+        return this.mExtendedCdmaRoaming;
+    }
+
     /**
      * Get current registered operator name in long alphanumeric format
      *
@@ -213,18 +283,19 @@
 
     @Override
     public int hashCode() {
-        return (mState * 0x1234)
+        return ((mState * 0x1234)
                 + (mRoaming ? 1 : 0)
                 + (mIsManualNetworkSelection ? 1 : 0)
                 + ((null == mOperatorAlphaLong) ? 0 : mOperatorAlphaLong.hashCode())
                 + ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
-                + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode());
+                + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
+                + (mExtendedCdmaRoaming));
     }
 
     @Override
     public boolean equals (Object o) {
         ServiceState s;
-        
+
         try {
             s = (ServiceState) o;
         } catch (ClassCastException ex) {
@@ -235,21 +306,66 @@
             return false;
         }
 
-        return mState == s.mState
+        return (mState == s.mState
                 && mRoaming == s.mRoaming
                 && mIsManualNetworkSelection == s.mIsManualNetworkSelection
                 && equalsHandlesNulls(mOperatorAlphaLong, s.mOperatorAlphaLong)
                 && equalsHandlesNulls(mOperatorAlphaShort, s.mOperatorAlphaShort)
-                && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric);
+                && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric)
+                && equalsHandlesNulls(mRadioTechnology, s.mRadioTechnology)
+                && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
+                && equalsHandlesNulls(mNetworkId, s.mNetworkId)
+                && equalsHandlesNulls(mSystemId, s.mSystemId)
+                && equalsHandlesNulls(mExtendedCdmaRoaming, s.mExtendedCdmaRoaming));
     }
 
     @Override
     public String toString() {
-        return mState + " " + (mRoaming ? "roaming" : "home")
+        String radioTechnology = new String("Error in radioTechnology");
+
+        switch(this.mRadioTechnology) {
+        case 0:
+            radioTechnology = "Unknown";
+            break;
+        case 1:
+            radioTechnology = "GPRS";
+            break;
+        case 2:
+            radioTechnology = "EDGE";
+            break;
+        case 3:
+            radioTechnology = "UMTS";
+            break;
+        case 4:
+            radioTechnology = "IS95A";
+            break;
+        case 5:
+            radioTechnology = "IS95B";
+            break;
+        case 6:
+            radioTechnology = "1xRTT";
+            break;
+        case 7:
+            radioTechnology = "EvDo rev. 0";
+            break;
+        case 8:
+            radioTechnology = "EvDo rev. A";
+            break;
+        default:
+            Log.w(LOG_TAG, "mRadioTechnology variable out of range.");
+        break;
+        }
+
+        return (mState + " " + (mRoaming ? "roaming" : "home")
                 + " " + mOperatorAlphaLong
                 + " " + mOperatorAlphaShort
                 + " " + mOperatorNumeric
-                + " " + (mIsManualNetworkSelection ? "(manual)" : "");
+                + " " + (mIsManualNetworkSelection ? "(manual)" : "")
+                + " " + radioTechnology
+                + " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
+                + "NetworkId: " + mNetworkId
+                + "SystemId: " + mSystemId
+                + "ExtendedCdmaRoaming: " + mExtendedCdmaRoaming);
     }
 
     public void setStateOutOfService() {
@@ -259,6 +375,11 @@
         mOperatorAlphaShort = null;
         mOperatorNumeric = null;
         mIsManualNetworkSelection = false;
+        mRadioTechnology = 0;
+        mCssIndicator = false;
+        mNetworkId = -1;
+        mSystemId = -1;
+        mExtendedCdmaRoaming = -1;
     }
 
     public void setStateOff() {
@@ -268,6 +389,11 @@
         mOperatorAlphaShort = null;
         mOperatorNumeric = null;
         mIsManualNetworkSelection = false;
+        mRadioTechnology = 0;
+        mCssIndicator = false;
+        mNetworkId = -1;
+        mSystemId = -1;
+        mExtendedCdmaRoaming = -1;
     }
 
     public void setState(int state) {
@@ -278,6 +404,11 @@
         mRoaming = roaming;
     }
 
+    /** @hide */
+    public void setExtendedCdmaRoaming (int roaming) {
+        this.mExtendedCdmaRoaming = roaming;
+    }
+
     public void setOperatorName(String longName, String shortName, String numeric) {
         mOperatorAlphaLong = longName;
         mOperatorAlphaShort = shortName;
@@ -287,7 +418,7 @@
     public void setIsManualSelection(boolean isManual) {
         mIsManualNetworkSelection = isManual;
     }
-    
+
     /**
      * Test whether two objects hold the same data values or both are null
      *
@@ -312,6 +443,11 @@
         mOperatorAlphaShort = m.getString("operator-alpha-short");
         mOperatorNumeric = m.getString("operator-numeric");
         mIsManualNetworkSelection = m.getBoolean("manual");
+        mRadioTechnology = m.getInt("radioTechnology");
+        mCssIndicator = m.getBoolean("cssIndicator");
+        mNetworkId = m.getInt("networkId");
+        mSystemId = m.getInt("systemId");
+        mExtendedCdmaRoaming = m.getInt("extendedCdmaRoaming");
     }
 
     /**
@@ -327,5 +463,47 @@
         m.putString("operator-alpha-short", mOperatorAlphaShort);
         m.putString("operator-numeric", mOperatorNumeric);
         m.putBoolean("manual", Boolean.valueOf(mIsManualNetworkSelection));
+        m.putInt("radioTechnology", mRadioTechnology);
+        m.putBoolean("cssIndicator", mCssIndicator);
+        m.putInt("networkId", mNetworkId);
+        m.putInt("systemId", mSystemId);
+        m.putInt("extendedCdmaRoaming", mExtendedCdmaRoaming);
+    }
+
+    //***** CDMA
+    /** @hide */
+    public void setRadioTechnology(int state) {
+        this.mRadioTechnology = state;
+    }
+
+    /** @hide */
+    public void setCssIndicator(int css) {
+        this.mCssIndicator = (css != 0);
+    }
+
+    /** @hide */
+    public void setSystemAndNetworkId(int systemId, int networkId) {
+        this.mSystemId = systemId;
+        this.mNetworkId = networkId;
+    }
+
+    /** @hide */
+    public int getRadioTechnology() {
+        return this.mRadioTechnology;
+    }
+
+    /** @hide */
+    public int getCssIndicator() {
+        return this.mCssIndicator ? 1 : 0;
+    }
+
+    /** @hide */
+    public int getNetworkId() {
+        return this.mNetworkId;
+    }
+
+    /** @hide */
+    public int getSystemId() {
+        return this.mSystemId;
     }
 }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
new file mode 100644
index 0000000..9395d66
--- /dev/null
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.app.PendingIntent;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.ISms;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.SmsRawData;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static android.telephony.SmsMessage.ENCODING_7BIT;
+import static android.telephony.SmsMessage.ENCODING_8BIT;
+import static android.telephony.SmsMessage.ENCODING_16BIT;
+import static android.telephony.SmsMessage.ENCODING_UNKNOWN;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+
+/**
+ * Manages SMS operations such as sending data, text, and pdu SMS messages.
+ * Get this object by calling the static method SmsManager.getDefault().
+ * @hide
+ */
+public final class SmsManager {
+    private static SmsManager sInstance;
+
+    /**
+     * Send a text based SMS.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *  the current default SMSC
+     * @param text the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or text are empty
+     */
+    public void sendTextMessage(
+            String destinationAddress, String scAddress, String text,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (TextUtils.isEmpty(text)) {
+            throw new IllegalArgumentException("Invalid message body");
+        }
+
+        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
+                scAddress, destinationAddress, text, (deliveryIntent != null));
+        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+    }
+
+    /**
+     * Divide a text message into several messages, none bigger than
+     * the maximum SMS message size.
+     *
+     * @param text the original message.  Must not be null.
+     * @return an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     */
+    public ArrayList<String> divideMessage(String text) {
+        int size = text.length();
+        int[] params = SmsMessage.calculateLength(text, false);
+            /* SmsMessage.calculateLength returns an int[4] with:
+             *   int[0] being the number of SMS's required,
+             *   int[1] the number of code units used,
+             *   int[2] is the number of code units remaining until the next message.
+             *   int[3] is the encoding type that should be used for the message.
+             */
+        int messageCount = params[0];
+        int encodingType = params[3];
+        ArrayList<String> result = new ArrayList<String>(messageCount);
+
+        int start = 0;
+        int limit;
+
+        if (messageCount > 1) {
+            limit = (encodingType == ENCODING_7BIT)?
+                MAX_USER_DATA_SEPTETS_WITH_HEADER: MAX_USER_DATA_BYTES_WITH_HEADER;
+        } else {
+            limit = (encodingType == ENCODING_7BIT)?
+                MAX_USER_DATA_SEPTETS: MAX_USER_DATA_BYTES;
+        }
+
+        try {
+            while (start < size) {
+                int end = GsmAlphabet.findLimitIndex(text, start, limit, encodingType);
+                result.add(text.substring(start, end));
+                start = end;
+            }
+        }
+        catch (EncodeException e) {
+            // ignore it.
+        }
+        return result;
+    }
+
+    /**
+     * Send a multi-part text based SMS.  The callee should have already
+     * divided the message into correctly sized parts by calling
+     * <code>divideMessage</code>.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     *   The per-application based SMS control checks sentIntent. If sentIntent
+     *   is NULL the caller will be checked against all unknown applicaitons,
+     *   which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     */
+    public void sendMultipartTextMessage(
+            String destinationAddress, String scAddress, ArrayList<String> parts,
+            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+        if (parts == null || parts.size() < 1) {
+            throw new IllegalArgumentException("Invalid message body");
+        }
+
+        if (parts.size() > 1) {
+            try {
+                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+                if (iccISms != null) {
+                    iccISms.sendMultipartText(destinationAddress, scAddress, parts,
+                            sentIntents, deliveryIntents);
+                }
+            } catch (RemoteException ex) {
+                // ignore it
+            }
+        } else {
+            PendingIntent sentIntent = null;
+            PendingIntent deliveryIntent = null;
+            if (sentIntents != null && sentIntents.size() > 0) {
+                sentIntent = sentIntents.get(0);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > 0) {
+                deliveryIntent = deliveryIntents.get(0);
+            }
+            sendTextMessage(destinationAddress, scAddress, parts.get(0),
+                    sentIntent, deliveryIntent);
+        }
+    }
+
+    /**
+     * Send a data based SMS to a specific application port.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *  the current default SMSC
+     * @param destinationPort the port to deliver the message to
+     * @param data the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     */
+    public void sendDataMessage(
+            String destinationAddress, String scAddress, short destinationPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (data == null || data.length == 0) {
+            throw new IllegalArgumentException("Invalid message data");
+        }
+
+        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
+                scAddress, destinationAddress,
+                destinationPort, data, (deliveryIntent != null));
+        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+    }
+
+    /**
+     * Send a raw SMS PDU.
+     *
+     * @param smsc the SMSC to send the message through, or NULL for the
+     *  default SMSC
+     * @param pdu the raw PDU to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @hide
+     */
+    private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                iccISms.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Get the default instance of the SmsManager
+     *
+     * @return the default instance of the SmsManager
+     */
+    public static SmsManager getDefault() {
+        if (sInstance == null) {
+            sInstance = new SmsManager();
+        }
+        return sInstance;
+    }
+
+    private SmsManager() {
+        //nothing
+    }
+
+    /**
+     * Copy a raw SMS PDU to the ICC.
+     *
+     * @param smsc the SMSC for this message, or NULL for the default SMSC
+     * @param pdu the raw PDU to store
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean copyMessageToIcc(byte[] smsc, byte[] pdu, int status) {
+        boolean success = false;
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                success = iccISms.copyMessageToIccEf(status, pdu, smsc);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Delete the specified message from the ICC.
+     *
+     * @param messageIndex is the record index of the message on ICC
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean
+    deleteMessageFromIcc(int messageIndex) {
+        boolean success = false;
+        byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1];
+        Arrays.fill(pdu, (byte)0xff);
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                success = iccISms.updateMessageOnIccEf(messageIndex, STATUS_ON_ICC_FREE, pdu);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Update the specified message on the ICC.
+     *
+     * @param messageIndex record index of message to update
+     * @param newStatus new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
+     * @param pdu the raw PDU to store
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
+        boolean success = false;
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                success = iccISms.updateMessageOnIccEf(messageIndex, newStatus, pdu);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Retrieves all messages currently stored on ICC.
+     *
+     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
+     *
+     * {@hide}
+     */
+    public ArrayList<SmsMessage> getAllMessagesFromIcc() {
+        List<SmsRawData> records = null;
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                records = iccISms.getAllMessagesFromIccEf();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return createMessageListFromRawRecords(records);
+   }
+
+    /**
+     * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
+     * records returned by <code>getAllMessagesFromIcc()</code>
+     *
+     * @param records SMS EF records, returned by
+     *   <code>getAllMessagesFromIcc</code>
+     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
+     */
+    private ArrayList<SmsMessage> createMessageListFromRawRecords(List records) {
+        ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
+        if (records != null) {
+            int count = records.size();
+            for (int i = 0; i < count; i++) {
+                SmsRawData data = (SmsRawData)records.get(i);
+                // List contains all records, including "free" records (null)
+                if (data != null) {
+                    SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
+                    messages.add(sms);
+                }
+            }
+        }
+        return messages;
+    }
+
+    // see SmsMessage.getStatusOnIcc
+
+    /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_FREE      = 0;
+
+    /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_READ      = 1;
+
+    /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_UNREAD    = 3;
+
+    /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_SENT      = 5;
+
+    /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_UNSENT    = 7;
+
+    // SMS send failure result codes
+
+    /** Generic failure cause */
+    static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
+    /** Failed because radio was explicitly turned off */
+    static public final int RESULT_ERROR_RADIO_OFF          = 2;
+    /** Failed because no pdu provided */
+    static public final int RESULT_ERROR_NULL_PDU           = 3;
+    /** Failed because service is currently unavailable */
+    static public final int RESULT_ERROR_NO_SERVICE         = 4;
+}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
new file mode 100644
index 0000000..3b7f4b5
--- /dev/null
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
+
+import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
+
+
+/**
+ * A Short Message Service message.
+ * @hide
+ */
+public class SmsMessage {
+    private static final boolean LOCAL_DEBUG = true;
+    private static final String LOG_TAG = "SMS";
+
+    /**
+     * SMS Class enumeration.
+     * See TS 23.038.
+     *
+     */
+    public enum MessageClass{
+        UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
+    }
+
+    /** Unknown encoding scheme (see TS 23.038) */
+    public static final int ENCODING_UNKNOWN = 0;
+    /** 7-bit encoding scheme (see TS 23.038) */
+    public static final int ENCODING_7BIT = 1;
+    /** 8-bit encoding scheme (see TS 23.038) */
+    public static final int ENCODING_8BIT = 2;
+    /** 16-bit encoding scheme (see TS 23.038) */
+    public static final int ENCODING_16BIT = 3;
+
+    /** The maximum number of payload bytes per message */
+    public static final int MAX_USER_DATA_BYTES = 140;
+
+    /**
+     * The maximum number of payload bytes per message if a user data header
+     * is present.  This assumes the header only contains the
+     * CONCATENATED_8_BIT_REFERENCE element.
+     *
+     * @hide pending API Council approval to extend the public API
+     */
+    public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
+
+    /** The maximum number of payload septets per message */
+    public static final int MAX_USER_DATA_SEPTETS = 160;
+
+    /**
+     * The maximum number of payload septets per message if a user data header
+     * is present.  This assumes the header only contains the
+     * CONCATENATED_8_BIT_REFERENCE element.
+     */
+    public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
+
+    /** Contains actual SmsMessage. Only public for debugging and for framework layer.
+    * {@hide}
+    */
+    public SmsMessageBase mWrappedSmsMessage;
+
+    public static class SubmitPdu extends SubmitPduBase {
+
+        //Constructor
+        public SubmitPdu() {
+        }
+
+        /* {@hide} */
+        protected SubmitPdu(SubmitPduBase spb) {
+            this.encodedMessage = spb.encodedMessage;
+            this.encodedScAddress = spb.encodedScAddress;
+        }
+
+    }
+
+    // Constructor
+    public SmsMessage() {
+        this(getSmsFacility());
+    }
+
+    private SmsMessage(SmsMessageBase smb) {
+        mWrappedSmsMessage = smb;
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /**
+     * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the
+     * +CMT unsolicited response (PDU mode, of course)
+     *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
+     *
+     * Only public for debugging and for RIL
+     *
+     * {@hide}
+     */
+    public static SmsMessage newFromCMT(String[] lines){
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMT(lines);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @hide */
+    protected static SmsMessage newFromCMTI(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMTI(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMTI(line);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @hide */
+    public static SmsMessage newFromCDS(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCDS(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCDS(line);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @hide */
+    public static SmsMessage newFromParcel(Parcel p) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromParcel(p);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromParcel(p);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by SmsManager.getAllMessagesFromSim + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
+                    index, data);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord(
+                    index, data);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /**
+     * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
+     * length in bytes (not hex chars) less the SMSC header
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu);
+        } else {
+            return com.android.internal.telephony.gsm.SmsMessage.getTPLayerLengthForPDU(pdu);
+        }
+    }
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and
+     * the number of characters remaining until the next message, given the
+     * current encoding.
+     *
+     * @param messageBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the GSM
+     *         alphabet are counted as a single space char.  If false, a
+     *         messageBody containing non-GSM alphabet characters is calculated
+     *         for 16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1]
+     *         the number of code units used, and int[2] is the number of code
+     *         units remaining until the next message. int[3] is the encoding
+     *         type that should be used for the message.
+     */
+    public static int[] calculateLength(CharSequence messageBody, boolean use7bitOnly) {
+        int ret[] = new int[4];
+
+        try {
+            // Try GSM alphabet
+            int septets = GsmAlphabet.countGsmSeptets(messageBody, !use7bitOnly);
+            ret[1] = septets;
+            if (septets > MAX_USER_DATA_SEPTETS) {
+                ret[0] = (septets / MAX_USER_DATA_SEPTETS_WITH_HEADER) + 1;
+                ret[2] = MAX_USER_DATA_SEPTETS_WITH_HEADER
+                            - (septets % MAX_USER_DATA_SEPTETS_WITH_HEADER);
+            } else {
+                ret[0] = 1;
+                ret[2] = MAX_USER_DATA_SEPTETS - septets;
+            }
+            ret[3] = ENCODING_7BIT;
+        } catch (EncodeException ex) {
+            // fall back to UCS-2
+            int octets = messageBody.length() * 2;
+            ret[1] = messageBody.length();
+            if (octets > MAX_USER_DATA_BYTES) {
+                // 6 is the size of the user data header
+                ret[0] = (octets / MAX_USER_DATA_BYTES_WITH_HEADER) + 1;
+                ret[2] = (MAX_USER_DATA_BYTES_WITH_HEADER
+                            - (octets % MAX_USER_DATA_BYTES_WITH_HEADER))/2;
+            } else {
+                ret[0] = 1;
+                ret[2] = (MAX_USER_DATA_BYTES - octets)/2;
+            }
+            ret[3] = ENCODING_16BIT;
+        }
+
+        return ret;
+    }
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and
+     * the number of characters remaining until the next message, given the
+     * current encoding.
+     *
+     * @param messageBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the GSM
+     *         alphabet are counted as a single space char.  If false, a
+     *         messageBody containing non-GSM alphabet characters is calculated
+     *         for 16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1]
+     *         the number of code units used, and int[2] is the number of code
+     *         units remaining until the next message. int[3] is the encoding
+     *         type that should be used for the message.
+     */
+    public static int[] calculateLength(String messageBody, boolean use7bitOnly) {
+        return calculateLength((CharSequence)messageBody, use7bitOnly);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] header) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message, boolean statusReportRequested) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the dat for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, short destinationPort, byte[] data,
+            boolean statusReportRequested) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Returns the address of the SMS service center that relayed this message
+     * or null if there is none.
+     */
+    public String getServiceCenterAddress() {
+        return mWrappedSmsMessage.getServiceCenterAddress();
+    }
+
+    /**
+     * Returns the originating address (sender) of this SMS message in String
+     * form or null if unavailable
+     */
+    public String getOriginatingAddress() {
+        return mWrappedSmsMessage.getOriginatingAddress();
+    }
+
+    /**
+     * Returns the originating address, or email from address if this message
+     * was from an email gateway. Returns null if originating address
+     * unavailable.
+     */
+    public String getDisplayOriginatingAddress() {
+        return mWrappedSmsMessage.getDisplayOriginatingAddress();
+    }
+
+    /**
+     * Returns the message body as a String, if it exists and is text based.
+     * @return message body is there is one, otherwise null
+     */
+    public String getMessageBody() {
+        return mWrappedSmsMessage.getMessageBody();
+    }
+
+    /**
+     * Returns the class of this message.
+     */
+    public MessageClass getMessageClass() {
+        return mWrappedSmsMessage.getMessageClass();
+    }
+
+    /**
+     * Returns the message body, or email message body if this message was from
+     * an email gateway. Returns null if message body unavailable.
+     */
+    public String getDisplayMessageBody() {
+        return mWrappedSmsMessage.getDisplayMessageBody();
+    }
+
+    /**
+     * Unofficial convention of a subject line enclosed in parens empty string
+     * if not present
+     */
+    public String getPseudoSubject() {
+        return mWrappedSmsMessage.getPseudoSubject();
+    }
+
+    /**
+     * Returns the service centre timestamp in currentTimeMillis() format
+     */
+    public long getTimestampMillis() {
+        return mWrappedSmsMessage.getTimestampMillis();
+    }
+
+    /**
+     * Returns true if message is an email.
+     *
+     * @return true if this message came through an email gateway and email
+     *         sender / subject / parsed body are available
+     */
+    public boolean isEmail() {
+        return mWrappedSmsMessage.isEmail();
+    }
+
+     /**
+     * @return if isEmail() is true, body of the email sent through the gateway.
+     *         null otherwise
+     */
+    public String getEmailBody() {
+        return mWrappedSmsMessage.getEmailBody();
+    }
+
+    /**
+     * @return if isEmail() is true, email from address of email sent through
+     *         the gateway. null otherwise
+     */
+    public String getEmailFrom() {
+        return mWrappedSmsMessage.getEmailFrom();
+    }
+
+    /**
+     * Get protocol identifier.
+     */
+    public int getProtocolIdentifier() {
+        return mWrappedSmsMessage.getProtocolIdentifier();
+    }
+
+    /**
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
+     * SMS
+     */
+    public boolean isReplace() {
+        return mWrappedSmsMessage.isReplace();
+    }
+
+    /**
+     * Returns true for CPHS MWI toggle message.
+     *
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
+     *         B.4.2
+     */
+    public boolean isCphsMwiMessage() {
+        return mWrappedSmsMessage.isCphsMwiMessage();
+    }
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) clear message
+     */
+    public boolean isMWIClearMessage() {
+        return mWrappedSmsMessage.isMWIClearMessage();
+    }
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) set message
+     */
+    public boolean isMWISetMessage() {
+        return mWrappedSmsMessage.isMWISetMessage();
+    }
+
+    /**
+     * returns true if this message is a "Message Waiting Indication Group:
+     * Discard Message" notification and should not be stored.
+     */
+    public boolean isMwiDontStore() {
+        return mWrappedSmsMessage.isMwiDontStore();
+    }
+
+    /**
+     * returns the user data section minus the user data header if one was
+     * present.
+     */
+    public byte[] getUserData() {
+        return mWrappedSmsMessage.getUserData();
+    }
+
+    /* Not part of the SDK interface and only needed by specific classes:
+       protected SmsHeader getUserDataHeader()
+    */
+
+    /**
+     * Returns the raw PDU for the message.
+     *
+     * @return the raw PDU for the message.
+     */
+    public byte[] getPdu() {
+        return mWrappedSmsMessage.getPdu();
+    }
+
+    /**
+     * Returns the status of the message on the SIM (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the SIM.  These are:
+     *         SmsManager.STATUS_ON_SIM_FREE
+     *         SmsManager.STATUS_ON_SIM_READ
+     *         SmsManager.STATUS_ON_SIM_UNREAD
+     *         SmsManager.STATUS_ON_SIM_SEND
+     *         SmsManager.STATUS_ON_SIM_UNSENT
+     * @deprecated Use getStatusOnIcc instead.
+     */
+    @Deprecated public int getStatusOnSim() {
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     */
+    public int getStatusOnIcc() {
+
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the record index of the message on the SIM (1-based index).
+     * @return the record index of the message on the SIM, or -1 if this
+     *         SmsMessage was not created from a SIM SMS EF record.
+     * @deprecated Use getIndexOnIcc instead.
+     */
+    @Deprecated public int getIndexOnSim() {
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     */
+    public int getIndexOnIcc() {
+
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * GSM:
+     * For an SMS-STATUS-REPORT message, this returns the status field from
+     * the status report.  This field indicates the status of a previously
+     * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
+     * description of values.
+     * CDMA:
+     * For not interfering with status codes from GSM, the value is
+     * shifted to the bits 31-16.
+     * The value is composed of an error class (bits 25-24) and a status code (bits 23-16).
+     * Possible codes are described in C.S0015-B, v2.0, 4.5.21.
+     *
+     * @return 0 indicates the previously sent message was received.
+     *         See TS 23.040, 9.9.2.3.15 and C.S0015-B, v2.0, 4.5.21
+     *         for a description of other possible values.
+     */
+    public int getStatus() {
+        return mWrappedSmsMessage.getStatus();
+    }
+
+    /**
+     * Return true iff the message is a SMS-STATUS-REPORT message.
+     */
+    public boolean isStatusReportMessage() {
+        return mWrappedSmsMessage.isStatusReportMessage();
+    }
+
+    /**
+     * Returns true iff the <code>TP-Reply-Path</code> bit is set in
+     * this message.
+     */
+    public boolean isReplyPathPresent() {
+        return mWrappedSmsMessage.isReplyPathPresent();
+    }
+
+    /** This method returns the reference to a specific
+     *  SmsMessage object, which is used for accessing its static methods.
+     * @return Specific SmsMessage.
+     */
+    private static final SmsMessageBase getSmsFacility(){
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return new com.android.internal.telephony.cdma.SmsMessage();
+        } else {
+            return new com.android.internal.telephony.gsm.SmsMessage();
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c7166ce..559542a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -28,25 +28,31 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.telephony.CellLocation;
 
+import com.android.internal.telephony.IPhoneSubInfo;
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyProperties;
 
 /**
  * Provides access to information about the telephony services on
  * the device. Applications can use the methods in this class to
  * determine telephony services and states, as well as to access some
- * types of subscriber information. Applications can also register 
- * a listener to receive notification of telephony state changes. 
+ * types of subscriber information. Applications can also register
+ * a listener to receive notification of telephony state changes.
  * <p>
  * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through 
+ * a reference to an instance through
  * {@link android.content.Context#getSystemService
  * Context.getSystemService(Context.TELEPHONY_SERVICE)}.
  * <p>
  * Note that acess to some telephony information is
- * permission-protected. Your application cannot access the protected 
- * information unless it has the appropriate permissions declared in 
- * its manifest file. Where permissions apply, they are noted in the  
- * the methods through which you access the protected information. 
+ * permission-protected. Your application cannot access the protected
+ * information unless it has the appropriate permissions declared in
+ * its manifest file. Where permissions apply, they are noted in the
+ * the methods through which you access the protected information.
  */
 public class TelephonyManager {
     private static final String TAG = "TelephonyManager";
@@ -154,10 +160,10 @@
     //
 
     /**
-     * Returns the software version number for the device, for example, 
+     * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones.
      *
-     * <p>Requires Permission: 
+     * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceSoftwareVersion() {
@@ -169,10 +175,10 @@
     }
 
     /**
-     * Returns the unique device ID, for example,the IMEI for GSM
+     * Returns the unique device ID, for example, the IMEI for GSM and the MEID for CDMA
      * phones.
      *
-     * <p>Requires Permission: 
+     * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceId() {
@@ -202,7 +208,7 @@
      * Enables location update notifications.  {@link PhoneStateListener#onCellLocationChanged
      * PhoneStateListener.onCellLocationChanged} will be called on location updates.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES 
+     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
      * CONTROL_LOCATION_UPDATES}
      *
      * @hide
@@ -258,23 +264,37 @@
     public static final int PHONE_TYPE_GSM = 1;
 
     /**
-     * Returns a constant indicating the device phone type. 
-     * 
+     * CDMA phone
+     * @hide
+     */
+    public static final int PHONE_TYPE_CDMA = 2;
+
+    /**
+     * Returns a constant indicating the device phone type.
+     *
      * @see #PHONE_TYPE_NONE
      * @see #PHONE_TYPE_GSM
+     * @see #PHONE_TYPE_CDMA
      */
     public int getPhoneType() {
-        // in the future, we should really check this
-        return PHONE_TYPE_GSM;
+        try{
+            if(getITelephony().getActivePhoneType() == RILConstants.CDMA_PHONE) {
+                return PHONE_TYPE_CDMA;
+            } else {
+                return PHONE_TYPE_GSM;
+            }
+        }catch(RemoteException ex){
+            return PHONE_TYPE_NONE;
+        }
     }
 
     //
-    // 
+    //
     // Current Network
     //
     //
 
-    /** 
+    /**
      * Returns the alphabetic name of current registered operator.
      * <p>
      * Availability: Only when user is registered to a network
@@ -283,7 +303,7 @@
         return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA);
     }
 
-    /** 
+    /**
      * Returns the numeric name (MCC+MNC) of current registered operator.
      * <p>
      * Availability: Only when user is registered to a network
@@ -292,7 +312,7 @@
         return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);
     }
 
-    /**  
+    /**
      * Returns true if the device is considered roaming on the current
      * network, for GSM purposes.
      * <p>
@@ -302,7 +322,7 @@
         return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
     }
 
-    /** 
+    /**
      * Returns the ISO country code equivilent of the current registered
      * operator's MCC (Mobile Country Code).
      * <p>
@@ -320,9 +340,20 @@
     public static final int NETWORK_TYPE_EDGE = 2;
     /** Current network is UMTS */
     public static final int NETWORK_TYPE_UMTS = 3;
+    /** Current network is CDMA: Either IS95A or IS95B*/
+    /** @hide */
+    public static final int NETWORK_TYPE_CDMA = 4;
+    /** Current network is EVDO revision 0 or revision A*/
+    /** @hide */
+    public static final int NETWORK_TYPE_EVDO_0 = 5;
+    /** @hide */
+    public static final int NETWORK_TYPE_EVDO_A = 6;
+    /** Current network is 1xRTT*/
+    /** @hide */
+    public static final int NETWORK_TYPE_1xRTT = 7;
 
     /**
-     * Returns a constant indicating the radio technology (network type) 
+     * Returns a constant indicating the radio technology (network type)
      * currently in use on the device.
      * @return the network type
      *
@@ -330,6 +361,10 @@
      * @see #NETWORK_TYPE_GPRS
      * @see #NETWORK_TYPE_EDGE
      * @see #NETWORK_TYPE_UMTS
+     * @see #NETWORK_TYPE_CDMA
+     * @see #NETWORK_TYPE_EVDO_0
+     * @see #NETWORK_TYPE_EVDO_A
+     * @see #NETWORK_TYPE_1xRTT
      */
     public int getNetworkType() {
         String prop = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE);
@@ -342,6 +377,18 @@
         else if ("UMTS".equals(prop)) {
             return NETWORK_TYPE_UMTS;
         }
+        else if ("CDMA".equals(prop)) {
+            return NETWORK_TYPE_CDMA;
+                }
+        else if ("CDMA - EvDo rev. 0".equals(prop)) {
+            return NETWORK_TYPE_EVDO_0;
+            }
+        else if ("CDMA - EvDo rev. A".equals(prop)) {
+            return NETWORK_TYPE_EVDO_A;
+            }
+        else if ("CDMA - 1xRTT".equals(prop)) {
+            return NETWORK_TYPE_1xRTT;
+            }
         else {
             return NETWORK_TYPE_UNKNOWN;
         }
@@ -362,6 +409,14 @@
                 return "EDGE";
             case NETWORK_TYPE_UMTS:
                 return "UMTS";
+            case NETWORK_TYPE_CDMA:
+                return "CDMA";
+            case NETWORK_TYPE_EVDO_0:
+                return "CDMA - EvDo rev. 0";
+            case NETWORK_TYPE_EVDO_A:
+                return "CDMA - EvDo rev. A";
+            case NETWORK_TYPE_1xRTT:
+                return "CDMA - 1xRTT";
             default:
                 return "UNKNOWN";
         }
@@ -375,7 +430,7 @@
 
     /** SIM card state: Unknown. Signifies that the SIM is in transition
      *  between states. For example, when the user inputs the SIM pin
-     *  under PIN_REQUIRED state, a query for sim status returns 
+     *  under PIN_REQUIRED state, a query for sim status returns
      *  this state before turning to SIM_STATE_READY. */
     public static final int SIM_STATE_UNKNOWN = 0;
     /** SIM card state: no SIM card is available in the device */
@@ -388,11 +443,11 @@
     public static final int SIM_STATE_NETWORK_LOCKED = 4;
     /** SIM card state: Ready */
     public static final int SIM_STATE_READY = 5;
-    
-    /** 
-     * Returns a constant indicating the state of the 
+
+    /**
+     * Returns a constant indicating the state of the
      * device SIM card.
-     * 
+     *
      * @see #SIM_STATE_UNKNOWN
      * @see #SIM_STATE_ABSENT
      * @see #SIM_STATE_PIN_REQUIRED
@@ -422,7 +477,7 @@
         }
     }
 
-    /** 
+    /**
      * Returns the MCC+MNC (mobile country code + mobile network code) of the
      * provider of the SIM. 5 or 6 decimal digits.
      * <p>
@@ -431,36 +486,36 @@
      * @see #getSimState
      */
     public String getSimOperator() {
-        return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC);
+        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
     }
 
-    /** 
-     * Returns the Service Provider Name (SPN). 
+    /**
+     * Returns the Service Provider Name (SPN).
      * <p>
      * Availability: SIM state must be {@link #SIM_STATE_READY}
      *
      * @see #getSimState
      */
     public String getSimOperatorName() {
-        return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA);
+        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA);
     }
 
-    /** 
+    /**
      * Returns the ISO country code equivalent for the SIM provider's country code.
      */
     public String getSimCountryIso() {
-        return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ISO_COUNTRY);
+        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY);
     }
 
     /**
      * Returns the serial number of the SIM, if applicable.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getSimSerialNumber() {
         try {
-            return getSubscriberInfo().getSimSerialNumber();
+            return getSubscriberInfo().getIccSerialNumber();
         } catch (RemoteException ex) {
         }
         return null;
@@ -475,7 +530,7 @@
     /**
      * Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getSubscriberId() {
@@ -487,10 +542,10 @@
     }
 
     /**
-     * Returns the phone number string for line 1, for example, the MSISDN 
+     * Returns the phone number string for line 1, for example, the MSISDN
      * for a GSM phone.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getLine1Number() {
@@ -502,9 +557,9 @@
     }
 
     /**
-     * Returns the alphabetic identifier associated with the line 1 number. 
+     * Returns the alphabetic identifier associated with the line 1 number.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      * nobody seems to call this.
@@ -520,7 +575,7 @@
     /**
      * Returns the voice mail number.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getVoiceMailNumber() {
@@ -535,7 +590,7 @@
      * Retrieves the alphabetic identifier associated with the voice
      * mail number.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getVoiceMailAlphaTag() {
@@ -555,10 +610,10 @@
     /** Device call state: No activity. */
     public static final int CALL_STATE_IDLE = 0;
     /** Device call state: Ringing. A new call arrived and is
-     *  ringing or waiting. In the latter case, another call is 
+     *  ringing or waiting. In the latter case, another call is
      *  already active. */
     public static final int CALL_STATE_RINGING = 1;
-    /** Device call state: Off-hook. At least one call exists 
+    /** Device call state: Off-hook. At least one call exists
       * that is dialing, active, or on hold, and no calls are ringing
       * or waiting. */
     public static final int CALL_STATE_OFFHOOK = 2;
@@ -609,13 +664,13 @@
     public static final int DATA_CONNECTING     = 1;
     /** Data connection state: Connected. IP traffic should be available. */
     public static final int DATA_CONNECTED      = 2;
-    /** Data connection state: Suspended. The connection is up, but IP 
-     * traffic is temporarily unavailable. For example, in a 2G network, 
+    /** Data connection state: Suspended. The connection is up, but IP
+     * traffic is temporarily unavailable. For example, in a 2G network,
      * data activity may be suspended when a voice call arrives. */
     public static final int DATA_SUSPENDED      = 3;
 
     /**
-     * Returns a constant indicating the current data connection state 
+     * Returns a constant indicating the current data connection state
      * (cellular).
      *
      * @see #DATA_DISCONNECTED
@@ -643,26 +698,26 @@
     //
 
     /**
-     * Registers a listener object to receive notification of changes 
-     * in specified telephony states. 
+     * Registers a listener object to receive notification of changes
+     * in specified telephony states.
      * <p>
      * To register a listener, pass a {@link PhoneStateListener}
-     * and specify at least one telephony state of interest in 
-     * the events argument. 
-     * 
+     * and specify at least one telephony state of interest in
+     * the events argument.
+     *
      * At registration, and when a specified telephony state
-     * changes, the telephony manager invokes the appropriate 
-     * callback method on the listener object and passes the 
+     * changes, the telephony manager invokes the appropriate
+     * callback method on the listener object and passes the
      * current (udpated) values.
      * <p>
      * To unregister a listener, pass the listener object and set the
-     * events argument to 
+     * events argument to
      * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
-     * 
+     *
      * @param listener The {@link PhoneStateListener} object to register
      *                 (or unregister)
      * @param events The telephony state(s) of interest to the listener,
-     *               as a bitwise-OR combination of {@link PhoneStateListener} 
+     *               as a bitwise-OR combination of {@link PhoneStateListener}
      *               LISTEN_ flags.
      */
     public void listen(PhoneStateListener listener, int events) {
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
new file mode 100644
index 0000000..189959b
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cdma;
+
+import android.os.Bundle;
+import android.telephony.CellLocation;
+
+/**
+ * Represents the cell location on a GSM phone.
+ * @hide
+ */
+public class CdmaCellLocation extends CellLocation {
+    private int mBaseStationId = -1;
+    private int mBaseStationLatitude = -1;
+    private int mBaseStationLongitude = -1;
+
+    /**
+     * Empty constructor.  Initializes the LAC and CID to -1.
+     */
+    public CdmaCellLocation() {
+        this.mBaseStationId = -1;
+        this.mBaseStationLatitude = -1;
+        this.mBaseStationLongitude = -1;
+    }
+
+    /**
+     * Initialize the object from a bundle.
+     */
+    public CdmaCellLocation(Bundle bundleWithValues) {
+        this.mBaseStationId = bundleWithValues.getInt("baseStationId");
+        this.mBaseStationLatitude = bundleWithValues.getInt("baseStationLatitude");
+        this.mBaseStationLongitude = bundleWithValues.getInt("baseStationLongitude");
+    }
+
+    /**
+     * @return cdma base station identification number, -1 if unknown
+     */
+    public int getBaseStationId() {
+        return this.mBaseStationId;
+    }
+
+    /**
+     * @return cdma base station latitude, -1 if unknown
+     */
+    public int getBaseStationLatitude() {
+        return this.mBaseStationLatitude;
+    }
+
+    /**
+     * @return cdma base station longitude, -1 if unknown
+     */
+    public int getBaseStationLongitude() {
+        return this.mBaseStationLongitude;
+    }
+
+    /**
+     * Invalidate this object.  The cell location data is set to -1.
+     */
+    public void setStateInvalid() {
+        this.mBaseStationId = -1;
+        this.mBaseStationLatitude = -1;
+        this.mBaseStationLongitude = -1;
+    }
+
+    /**
+     * Set the cell location data.
+     */
+     public void setCellLocationData(int baseStationId, int baseStationLatitude,
+         int baseStationLongitude) {
+         // The following values have to be written in the correct sequence
+         this.mBaseStationId = baseStationId;
+         this.mBaseStationLatitude = baseStationLatitude;   //values[2];
+         this.mBaseStationLongitude = baseStationLongitude; //values[3];
+    }
+
+    @Override
+    public int hashCode() {
+        return this.mBaseStationId ^ this.mBaseStationLatitude ^ this.mBaseStationLongitude;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        CdmaCellLocation s;
+
+        try {
+            s = (CdmaCellLocation)o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return (equalsHandlesNulls(this.mBaseStationId, s.mBaseStationId) &&
+                equalsHandlesNulls(this.mBaseStationLatitude, s.mBaseStationLatitude) &&
+                equalsHandlesNulls(this.mBaseStationLongitude, s.mBaseStationLongitude)
+        );
+    }
+
+    @Override
+    public String toString() {
+        return "[" + this.mBaseStationId + ","
+                   + this.mBaseStationLatitude + ","
+                   + this.mBaseStationLongitude + "]";
+    }
+
+    /**
+     * Test whether two objects hold the same data values or both are null
+     *
+     * @param a first obj
+     * @param b second obj
+     * @return true if two objects equal or both are null
+     */
+    private static boolean equalsHandlesNulls(Object a, Object b) {
+        return (a == null) ? (b == null) : a.equals (b);
+    }
+
+    /**
+     * Fill the cell location data into the intent notifier Bundle based on service state
+     *
+     * @param bundleToFill intent notifier Bundle
+     */
+    public void fillInNotifierBundle(Bundle bundleToFill) {
+        bundleToFill.putInt("baseStationId", this.mBaseStationId);
+        bundleToFill.putInt("baseStationLatitude", this.mBaseStationLatitude);
+        bundleToFill.putInt("baseStationLongitude", this.mBaseStationLongitude);
+    }
+
+}
+
+
diff --git a/telephony/java/android/telephony/cdma/package.html b/telephony/java/android/telephony/cdma/package.html
new file mode 100644
index 0000000..ee4af5e
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/package.html
@@ -0,0 +1,5 @@
+<HTML>
+<BODY>
+Provides APIs for utilizing CDMA-specific telephony features.
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index fb9b73a..637a11c 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -17,14 +17,12 @@
 package android.telephony.gsm;
 
 import android.os.Bundle;
-import com.android.internal.telephony.Phone;
 import android.telephony.CellLocation;
 
 /**
  * Represents the cell location on a GSM phone.
  */
-public class GsmCellLocation extends CellLocation
-{
+public class GsmCellLocation extends CellLocation {
     private int mLac;
     private int mCid;
 
@@ -82,7 +80,7 @@
     @Override
     public boolean equals(Object o) {
         GsmCellLocation s;
-        
+
         try {
             s = (GsmCellLocation)o;
         } catch (ClassCastException ex) {
@@ -100,7 +98,7 @@
     public String toString() {
         return "["+ mLac + "," + mCid + "]";
     }
-    
+
     /**
      * Test whether two objects hold the same data values or both are null
      *
diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java
index c63b530..cdd707e 100644
--- a/telephony/java/android/telephony/gsm/SmsManager.java
+++ b/telephony/java/android/telephony/gsm/SmsManager.java
@@ -17,28 +17,35 @@
 package android.telephony.gsm;
 
 import android.app.PendingIntent;
-import android.os.RemoteException;
-import android.os.IServiceManager;
-import android.os.ServiceManager;
-import android.os.ServiceManagerNative;
-import android.text.TextUtils;
-
-import com.android.internal.telephony.gsm.EncodeException;
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.ISms;
-import com.android.internal.telephony.gsm.SimConstants;
-import com.android.internal.telephony.gsm.SmsRawData;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+
 
 /**
  * Manages SMS operations such as sending data, text, and pdu SMS messages.
  * Get this object by calling the static method SmsManager.getDefault().
+ * @deprecated Replaced by android.telephony.SmsManager that supports both GSM and CDMA.
  */
-public final class SmsManager {
+@Deprecated public final class SmsManager {
     private static SmsManager sInstance;
+    private android.telephony.SmsManager mSmsMgrProxy;
+
+    /** Get the default instance of the SmsManager
+     *
+     * @return the default instance of the SmsManager
+     * @deprecated Use android.telephony.SmsManager.
+     */
+    @Deprecated
+    public static final SmsManager getDefault() {
+        if (sInstance == null) {
+            sInstance = new SmsManager();
+        }
+        return sInstance;
+    }
+
+    private SmsManager() {
+        mSmsMgrProxy = android.telephony.SmsManager.getDefault();
+    }
 
     /**
      * Send a text based SMS.
@@ -55,28 +62,21 @@
      *  <code>RESULT_ERROR_RADIO_OFF</code>
      *  <code>RESULT_ERROR_NULL_PDU</code>.
      *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  is NULL the caller will be checked against all unknown applications,
      *  which cause smaller number of SMS to be sent in checking period.
      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is delivered to the recipient.  The
      *  raw pdu of the status report is in the extended data ("pdu").
      *
      * @throws IllegalArgumentException if destinationAddress or text are empty
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public void sendTextMessage(
+    @Deprecated
+    public final void sendTextMessage(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent) {
-        if (TextUtils.isEmpty(destinationAddress)) {
-            throw new IllegalArgumentException("Invalid destinationAddress");
-        }
-
-        if (TextUtils.isEmpty(text)) {
-            throw new IllegalArgumentException("Invalid message body");
-        }
-
-        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
-                scAddress, destinationAddress, text, (deliveryIntent != null));
-        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+        mSmsMgrProxy.sendTextMessage(destinationAddress, scAddress, text,
+                sentIntent, deliveryIntent);
     }
 
     /**
@@ -86,55 +86,24 @@
      * @param text the original message.  Must not be null.
      * @return an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public ArrayList<String> divideMessage(String text) {
-        int size = text.length();
-        int[] params = SmsMessage.calculateLength(text, false);
-            /* SmsMessage.calculateLength returns an int[4] with:
-             *   int[0] being the number of SMS's required,
-             *   int[1] the number of code units used,
-             *   int[2] is the number of code units remaining until the next message.
-             *   int[3] is the encoding type that should be used for the message.
-             */
-        int messageCount = params[0];
-        int encodingType = params[3];
-        ArrayList<String> result = new ArrayList<String>(messageCount);
-
-        int start = 0;
-        int limit;
-        
-        if (messageCount > 1) {
-            limit = (encodingType == SmsMessage.ENCODING_7BIT) ?
-                    SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER :
-                        SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;            
-        } else {
-            limit = (encodingType == SmsMessage.ENCODING_7BIT) ?
-                SmsMessage.MAX_USER_DATA_SEPTETS : SmsMessage.MAX_USER_DATA_BYTES;            
-        }
-
-        try {
-            while (start < size) {
-                int end = GsmAlphabet.findLimitIndex(text, start, limit, encodingType);
-                result.add(text.substring(start, end));
-                start = end;
-            }
-        } catch (EncodeException e) {
-            // ignore it.
-        }
-        return result;
+    @Deprecated
+    public final ArrayList<String> divideMessage(String text) {
+        return mSmsMgrProxy.divideMessage(text);
     }
 
     /**
      * Send a multi-part text based SMS.  The callee should have already
      * divided the message into correctly sized parts by calling
      * <code>divideMessage</code>.
-     * 
+     *
      * @param destinationAddress the address to send the message to
      * @param scAddress is the service center address or null to use
      *   the current default SMSC
      * @param parts an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of 
+     * @param sentIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been sent.
      *   The result code will be <code>Activity.RESULT_OK<code> for success,
@@ -145,44 +114,21 @@
      *   The per-application based SMS control checks sentIntent. If sentIntent
      *   is NULL the caller will be checked against all unknown applicaitons,
      *   which cause smaller number of SMS to be sent in checking period.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of 
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been delivered
      *   to the recipient.  The raw pdu of the status report is in the
      *   extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public void sendMultipartTextMessage(
+    @Deprecated
+    public final void sendMultipartTextMessage(
             String destinationAddress, String scAddress, ArrayList<String> parts,
             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
-        if (TextUtils.isEmpty(destinationAddress)) {
-            throw new IllegalArgumentException("Invalid destinationAddress");
-        }
-        if (parts == null || parts.size() < 1) {
-            throw new IllegalArgumentException("Invalid message body");
-        }
-        
-        if (parts.size() > 1) {
-            try {
-                ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-                if (simISms != null) {
-                    simISms.sendMultipartText(destinationAddress, scAddress, parts,
-                            sentIntents, deliveryIntents);
-                }
-            } catch (RemoteException ex) {
-                // ignore it
-            }
-        } else {
-            PendingIntent sentIntent = null;
-            PendingIntent deliveryIntent = null;
-            if (sentIntents != null && sentIntents.size() > 0) {
-                sentIntent = sentIntents.get(0);
-            }
-            if (deliveryIntents != null && deliveryIntents.size() > 0) {
-                deliveryIntent = deliveryIntents.get(0);
-            }
-            sendTextMessage(destinationAddress, scAddress, parts.get(0),
-                    sentIntent, deliveryIntent);
-        }
+        mSmsMgrProxy.sendMultipartTextMessage(destinationAddress, scAddress, parts,
+                sentIntents, deliveryIntents);
     }
 
     /**
@@ -208,70 +154,14 @@
      *  raw pdu of the status report is in the extended data ("pdu").
      *
      * @throws IllegalArgumentException if destinationAddress or data are empty
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public void sendDataMessage(
+    @Deprecated
+    public final void sendDataMessage(
             String destinationAddress, String scAddress, short destinationPort,
             byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
-        if (TextUtils.isEmpty(destinationAddress)) {
-            throw new IllegalArgumentException("Invalid destinationAddress");
-        }
-
-        if (data == null || data.length == 0) {
-            throw new IllegalArgumentException("Invalid message data");
-        }
-
-        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
-                destinationPort, data, (deliveryIntent != null));
-        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
-    }
-
-    /**
-     * Send a raw SMS PDU.
-     *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  default SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>PendingIntent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
-     *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
-     *  which cause smaller number of SMS to be sent in checking period. 
-     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
-     *  broadcast when the message is delivered to the recipient.  The
-     *  raw pdu of the status report is in the extended data ("pdu").
-     *
-     */
-    private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                simISms.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-    }
-
-    /**
-     * Get the default instance of the SmsManager
-     *
-     * @return the default instance of the SmsManager
-     */
-    public static SmsManager getDefault() {
-        if (sInstance == null) {
-            sInstance = new SmsManager();
-        }
-        return sInstance;
-    }
-
-    private SmsManager() {
-        // nothing to see here
+        mSmsMgrProxy.sendDataMessage(destinationAddress, scAddress, destinationPort,
+                data, sentIntent, deliveryIntent);
     }
 
     /**
@@ -282,22 +172,12 @@
      * @param status message status (STATUS_ON_SIM_READ, STATUS_ON_SIM_UNREAD,
      *               STATUS_ON_SIM_SENT, STATUS_ON_SIM_UNSENT)
      * @return true for success
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public boolean copyMessageToSim(byte[] smsc, byte[] pdu, int status) {
-        boolean success = false;
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                success = simISms.copyMessageToSimEf(status, pdu, smsc);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return success;
+    @Deprecated
+    public final boolean copyMessageToSim(byte[] smsc, byte[] pdu, int status) {
+        return mSmsMgrProxy.copyMessageToIcc(smsc, pdu, status);
     }
 
     /**
@@ -305,26 +185,12 @@
      *
      * @param messageIndex is the record index of the message on SIM
      * @return true for success
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public boolean
-    deleteMessageFromSim(int messageIndex) {
-        boolean success = false;
-        byte[] pdu = new byte[SimConstants.SMS_RECORD_LENGTH-1];
-        Arrays.fill(pdu, (byte)0xff);
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                success = simISms.updateMessageOnSimEf(messageIndex,
-                        STATUS_ON_SIM_FREE, pdu);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return success;
+    @Deprecated
+    public final boolean deleteMessageFromSim(int messageIndex) {
+        return mSmsMgrProxy.deleteMessageFromIcc(messageIndex);
     }
 
     /**
@@ -336,97 +202,59 @@
      *                  STATUS_ON_SIM_UNSENT, STATUS_ON_SIM_FREE)
      * @param pdu the raw PDU to store
      * @return true for success
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public boolean updateMessageOnSim(int messageIndex, int newStatus,
-            byte[] pdu) {
-        boolean success = false;
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                success = simISms.updateMessageOnSimEf(messageIndex, newStatus, pdu);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return success;
+    @Deprecated
+    public final boolean updateMessageOnSim(int messageIndex, int newStatus, byte[] pdu) {
+        return mSmsMgrProxy.updateMessageOnIcc(messageIndex, newStatus, pdu);
     }
 
-
     /**
      * Retrieves all messages currently stored on SIM.
-     *
      * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public ArrayList<SmsMessage> getAllMessagesFromSim() {
-        List<SmsRawData> records = null;
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                records = simISms.getAllMessagesFromSimEf();
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-        
-        return createMessageListFromRawRecords(records); 
-   }
-
-    /**
-     * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
-     * records returned by <code>getAllMessagesFromSim()</code>
-     *
-     * @param records SMS EF records, returned by
-     *   <code>getAllMessagesFromSim</code>
-     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
-     */
-    private ArrayList<SmsMessage> createMessageListFromRawRecords(List records) {
-        ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
-        if (records != null) {
-            int count = records.size();
-            for (int i = 0; i < count; i++) {
-                SmsRawData data = (SmsRawData)records.get(i);
-                // List contains all records, including "free" records (null)
-                if (data != null) {
-                    SmsMessage sms =
-                            SmsMessage.createFromEfRecord(i+1, data.getBytes());
-                    messages.add(sms);
-                }
-            }
-        }
-        return messages;
+    @Deprecated
+    public final ArrayList<android.telephony.SmsMessage> getAllMessagesFromSim() {
+        return mSmsMgrProxy.getAllMessagesFromIcc();
     }
 
-    /** Free space (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_FREE      = 0;
+    /** Free space (TS 51.011 10.5.3).
+     *  @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_FREE      = 0;
 
-    /** Received and read (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_READ      = 1;
+    /** Received and read (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_READ      = 1;
 
-    /** Received and unread (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_UNREAD    = 3;
+    /** Received and unread (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_UNREAD    = 3;
 
-    /** Stored and sent (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_SENT      = 5;
+    /** Stored and sent (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_SENT      = 5;
 
-    /** Stored and unsent (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_UNSENT    = 7;
+    /** Stored and unsent (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_UNSENT    = 7;
 
+    /** Generic failure cause
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
 
-    // SMS send failure result codes
+    /** Failed because radio was explicitly turned off
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_RADIO_OFF          = 2;
 
-    /** Generic failure cause */
-    static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
-    /** Failed because radio was explicitly turned off */
-    static public final int RESULT_ERROR_RADIO_OFF          = 2;
-    /** Failed because no pdu provided */
-    static public final int RESULT_ERROR_NULL_PDU           = 3;
-    /** Failed because service is currently unavailable */
-    static public final int RESULT_ERROR_NO_SERVICE         = 4;
+    /** Failed because no pdu provided
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_NULL_PDU           = 3;
+
+    /** Failed because service is currently unavailable
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_NO_SERVICE         = 4;
+
 }
diff --git a/telephony/java/android/telephony/gsm/SmsMessage.java b/telephony/java/android/telephony/gsm/SmsMessage.java
index c2e0165..0928ddf 100644
--- a/telephony/java/android/telephony/gsm/SmsMessage.java
+++ b/telephony/java/android/telephony/gsm/SmsMessage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -16,327 +16,117 @@
 
 package android.telephony.gsm;
 
-import android.telephony.PhoneNumberUtils;
-import android.util.Config;
-import android.util.Log;
-import android.telephony.PhoneNumberUtils;
-import android.text.format.Time;
+import android.os.Parcel;
+import android.telephony.TelephonyManager;
 
-import com.android.internal.telephony.gsm.EncodeException;
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.SimUtils;
-import com.android.internal.telephony.gsm.SmsHeader;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
 
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 
-class SmsAddress {
-    // From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
-    static final int TON_UNKNOWN = 0;
+import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
 
-    static final int TON_INTERNATIONAL = 1;
-
-    static final int TON_NATIONAL = 2;
-
-    static final int TON_NETWORK = 3;
-
-    static final int TON_SUBSCRIBER = 4;
-
-    static final int TON_ALPHANUMERIC = 5;
-
-    static final int TON_APPREVIATED = 6;
-
-    static final int OFFSET_ADDRESS_LENGTH = 0;
-
-    static final int OFFSET_TOA = 1;
-
-    static final int OFFSET_ADDRESS_VALUE = 2;
-
-    int ton;
-
-    String address;
-
-    byte[] origBytes;
-
-    /**
-     * New SmsAddress from TS 23.040 9.1.2.5 Address Field
-     *
-     * @param offset the offset of the Address-Length byte
-     * @param length the length in bytes rounded up, e.g. "2 +
-     *        (addressLength + 1) / 2"
-     */
-
-    SmsAddress(byte[] data, int offset, int length) {
-        origBytes = new byte[length];
-        System.arraycopy(data, offset, origBytes, 0, length);
-
-        // addressLength is the count of semi-octets, not bytes
-        int addressLength = origBytes[OFFSET_ADDRESS_LENGTH] & 0xff;
-
-        int toa = origBytes[OFFSET_TOA] & 0xff;
-        ton = 0x7 & (toa >> 4);
-
-        // TOA must have its high bit set
-        if ((toa & 0x80) != 0x80) {
-            throw new RuntimeException("Invalid TOA - high bit must be set");
-        }
-
-        if (isAlphanumeric()) {
-            // An alphanumeric address
-            int countSeptets = addressLength * 4 / 7;
-
-            address = GsmAlphabet.gsm7BitPackedToString(origBytes,
-                    OFFSET_ADDRESS_VALUE, countSeptets);
-        } else {
-            // TS 23.040 9.1.2.5 says
-            // that "the MS shall interpret reserved values as 'Unknown'
-            // but shall store them exactly as received"
-
-            byte lastByte = origBytes[length - 1];
-
-            if ((addressLength & 1) == 1) {
-                // Make sure the final unused BCD digit is 0xf
-                origBytes[length - 1] |= 0xf0;
-            }
-            address = PhoneNumberUtils.calledPartyBCDToString(origBytes,
-                    OFFSET_TOA, length - OFFSET_TOA);
-
-            // And restore origBytes
-            origBytes[length - 1] = lastByte;
-        }
-    }
-
-    public String getAddressString() {
-        return address;
-    }
-
-    /**
-     * Returns true if this is an alphanumeric addres
-     */
-    public boolean isAlphanumeric() {
-        return ton == TON_ALPHANUMERIC;
-    }
-
-    public boolean isNetworkSpecific() {
-        return ton == TON_NETWORK;
-    }
-
-    /**
-     * Returns true of this is a valid CPHS voice message waiting indicator
-     * address
-     */
-    public boolean isCphsVoiceMessageIndicatorAddress() {
-        // CPHS-style MWI message
-        // See CPHS 4.7 B.4.2.1
-        //
-        // Basically:
-        //
-        // - Originating address should be 4 bytes long and alphanumeric
-        // - Decode will result with two chars:
-        // - Char 1
-        // 76543210
-        // ^ set/clear indicator (0 = clear)
-        // ^^^ type of indicator (000 = voice)
-        // ^^^^ must be equal to 0001
-        // - Char 2:
-        // 76543210
-        // ^ line number (0 = line 1)
-        // ^^^^^^^ set to 0
-        //
-        // Remember, since the alpha address is stored in 7-bit compact form,
-        // the "line number" is really the top bit of the first address value
-        // byte
-
-        return (origBytes[OFFSET_ADDRESS_LENGTH] & 0xff) == 4
-                && isAlphanumeric() && (origBytes[OFFSET_TOA] & 0x0f) == 0;
-    }
-
-    /**
-     * Returns true if this is a valid CPHS voice message waiting indicator
-     * address indicating a "set" of "indicator 1" of type "voice message
-     * waiting"
-     */
-    public boolean isCphsVoiceMessageSet() {
-        // 0x11 means "set" "voice message waiting" "indicator 1"
-        return isCphsVoiceMessageIndicatorAddress()
-                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x11;
-
-    }
-
-    /**
-     * Returns true if this is a valid CPHS voice message waiting indicator
-     * address indicationg a "clear" of "indicator 1" of type "voice message
-     * waiting"
-     */
-    public boolean isCphsVoiceMessageClear() {
-        // 0x10 means "clear" "voice message waiting" "indicator 1"
-        return isCphsVoiceMessageIndicatorAddress()
-                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x10;
-
-    }
-
-    public boolean couldBeEmailGateway() {
-        // Some carriers seems to send email gateway messages in this form:
-        // from: an UNKNOWN TON, 3 or 4 digits long, beginning with a 5
-        // PID: 0x00, Data coding scheme 0x03
-        // So we just attempt to treat any message from an address length <= 4
-        // as an email gateway
-
-        return address.length() <= 4;
-    }
-
-}
 
 /**
  * A Short Message Service message.
- *
+ * @deprecated Replaced by android.telephony.SmsMessage that supports both GSM and CDMA.
  */
+@Deprecated
 public class SmsMessage {
-    static final String LOG_TAG = "GSM";
+    private static final boolean LOCAL_DEBUG = true;
+    private static final String LOG_TAG = "SMS";
 
     /**
      * SMS Class enumeration.
      * See TS 23.038.
-     *
+     * @deprecated Use android.telephony.SmsMessage.
      */
-    public enum MessageClass {
+    @Deprecated
+    public enum MessageClass{
         UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
     }
 
-    /** Unknown encoding scheme (see TS 23.038) */
-    public static final int ENCODING_UNKNOWN = 0;
-    /** 7-bit encoding scheme (see TS 23.038) */
-    public static final int ENCODING_7BIT = 1;
-    /** 8-bit encoding scheme (see TS 23.038) */
-    public static final int ENCODING_8BIT = 2;
-    /** 16-bit encoding scheme (see TS 23.038) */
-    public static final int ENCODING_16BIT = 3;
+    /** Unknown encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_UNKNOWN = 0;
 
-    /** The maximum number of payload bytes per message */
-    public static final int MAX_USER_DATA_BYTES = 140;
+    /** 7-bit encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_7BIT = 1;
+
+    /** 8-bit encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_8BIT = 2;
+
+    /** 16-bit encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_16BIT = 3;
+
+    /** The maximum number of payload bytes per message
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int MAX_USER_DATA_BYTES = 140;
 
     /**
      * The maximum number of payload bytes per message if a user data header
      * is present.  This assumes the header only contains the
      * CONCATENATED_8_BIT_REFERENCE element.
-     * 
+     *
+     * @deprecated Use android.telephony.SmsMessage.
      * @hide pending API Council approval to extend the public API
      */
-    static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
+    @Deprecated public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
 
-    /** The maximum number of payload septets per message */
-    public static final int MAX_USER_DATA_SEPTETS = 160;
+    /** The maximum number of payload septets per message
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int MAX_USER_DATA_SEPTETS = 160;
 
     /**
      * The maximum number of payload septets per message if a user data header
      * is present.  This assumes the header only contains the
      * CONCATENATED_8_BIT_REFERENCE element.
+     * @deprecated Use android.telephony.SmsMessage.
      */
-    public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
+    @Deprecated public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
 
-    /** The address of the SMSC. May be null */
-    String scAddress;
-
-    /** The address of the sender */
-    SmsAddress originatingAddress;
-
-    /** The message body as a string. May be null if the message isn't text */
-    String messageBody;
-
-    String pseudoSubject;
-
-    /** Non-null  this is an email gateway message */
-    String emailFrom;
-
-    /** Non-null if this is an email gateway message */
-    String emailBody;
-
-    boolean isEmail;
-
-    long scTimeMillis;
-
-    /** The raw PDU of the message */
-    byte[] mPdu;
-
-    /** The raw bytes for the user data section of the message */
-    byte[] userData;
-
-    SmsHeader userDataHeader;
-
-    /**
-     * TP-Message-Type-Indicator
-     * 9.2.3
+    /** Contains actual SmsMessage. Only public for debugging and for framework layer.
+     * @deprecated Use android.telephony.SmsMessage.
+     * {@hide}
      */
-    int mti;
+    @Deprecated public SmsMessageBase mWrappedSmsMessage;
 
-    /** TP-Protocol-Identifier (TP-PID) */
-    int protocolIdentifier;
-
-    // TP-Data-Coding-Scheme
-    // see TS 23.038
-    int dataCodingScheme;
-
-    // TP-Reply-Path
-    // e.g. 23.040 9.2.2.1
-    boolean replyPathPresent = false;
-
-    // "Message Marked for Automatic Deletion Group"
-    // 23.038 Section 4
-    boolean automaticDeletion;
-
-    // "Message Waiting Indication Group"
-    // 23.038 Section 4
-    private boolean isMwi;
-
-    private boolean mwiSense;
-
-    private boolean mwiDontStore;
-
-    MessageClass messageClass;
-
-    /**
-     * Indicates status for messages stored on the SIM.
-     */
-    int statusOnSim = -1;
-
-    /**
-     * Record index of message in the EF.
-     */
-    int indexOnSim = -1;
-
-    /** TP-Message-Reference - Message Reference of sent message. @hide */
-    public int messageRef;
-
-    /** True if Status Report is for SMS-SUBMIT; false for SMS-COMMAND. */
-    boolean forSubmit;
-
-    /** The address of the receiver. */
-    SmsAddress recipientAddress;
-
-    /** Time when SMS-SUBMIT was delivered from SC to MSE. */
-    long dischargeTimeMillis;
-
-    /**
-     *  TP-Status - status of a previously submitted SMS.
-     *  This field applies to SMS-STATUS-REPORT messages.  0 indicates success;
-     *  see TS 23.040, 9.2.3.15 for description of other possible values.
-     */
-    int status;
-
-    /**
-     *  TP-Status - status of a previously submitted SMS.
-     *  This field is true iff the message is a SMS-STATUS-REPORT message.
-     */
-    boolean isStatusReportMessage = false;
-
-    /**
-     * This class represents the encoded form of an outgoing SMS.
-     */
+    /** @deprecated Use android.telephony.SmsMessage. */
+    @Deprecated
     public static class SubmitPdu {
-        public byte[] encodedScAddress; // Null if not applicable.
-        public byte[] encodedMessage;
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated public byte[] encodedScAddress; // Null if not applicable.
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated public byte[] encodedMessage;
 
+        //Constructor
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated
+        public SubmitPdu() {
+        }
+
+        /** @deprecated Use android.telephony.SmsMessage.
+         * {@hide}
+         */
+        @Deprecated
+        protected SubmitPdu(SubmitPduBase spb) {
+            this.encodedMessage = spb.encodedMessage;
+            this.encodedScAddress = spb.encodedScAddress;
+        }
+
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated
         public String toString() {
             return "SubmitPdu: encodedScAddress = "
                     + Arrays.toString(encodedScAddress)
@@ -345,18 +135,33 @@
         }
     }
 
+    // Constructor
+    /** @deprecated Use android.telephony.SmsMessage. */
+    @Deprecated
+    public SmsMessage() {
+        this(getSmsFacility());
+    }
+
+    private SmsMessage(SmsMessageBase smb) {
+        mWrappedSmsMessage = smb;
+    }
+
     /**
      * Create an SmsMessage from a raw PDU.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static SmsMessage createFromPdu(byte[] pdu) {
-        try {
-            SmsMessage msg = new SmsMessage();
-            msg.parsePdu(pdu);
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
-            return null;
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
         }
+
+        return new SmsMessage(wrappedMessage);
     }
 
     /**
@@ -364,38 +169,70 @@
      * +CMT unsolicited response (PDU mode, of course)
      *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
      *
-     * Only public for debugging
-     *
+     * Only public for debugging and for RIL
+     * @deprecated Use android.telephony.SmsMessage.
      * {@hide}
      */
-    /* package */ public static SmsMessage newFromCMT(String[] lines) {
-        try {
-            SmsMessage msg = new SmsMessage();
-            msg.parsePdu(SimUtils.hexStringToBytes(lines[1]));
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
-            return null;
+    @Deprecated
+    public static SmsMessage newFromCMT(String[] lines){
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMT(lines);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines);
         }
+
+        return new SmsMessage(wrappedMessage);
     }
 
-    /* pacakge */ static SmsMessage newFromCMTI(String line) {
-        // the thinking here is not to read the message immediately
-        // FTA test case
-        Log.e(LOG_TAG, "newFromCMTI: not yet supported");
-        return null;
+    /** @deprecated Use android.telephony.SmsMessage.
+     *  @hide */
+    @Deprecated
+    protected static SmsMessage newFromCMTI(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMTI(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMTI(line);
+        }
+
+        return new SmsMessage(wrappedMessage);
     }
 
-    /** @hide */
-    /* package */ public static SmsMessage newFromCDS(String line) {
-        try {
-            SmsMessage msg = new SmsMessage();
-            msg.parsePdu(SimUtils.hexStringToBytes(line));
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "CDS SMS PDU parsing failed: ", ex);
-            return null;
+    /** @deprecated Use android.telephony.SmsMessage.
+     *  @hide */
+    @Deprecated
+    public static SmsMessage newFromCDS(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCDS(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCDS(line);
         }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @deprecated Use android.telephony.SmsMessage.
+     *  @hide */
+    @Deprecated
+    public static SmsMessage newFromParcel(Parcel p) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromParcel(p);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromParcel(p);
+        }
+
+        return new SmsMessage(wrappedMessage);
     }
 
     /**
@@ -405,51 +242,40 @@
      *              returned by SmsManager.getAllMessagesFromSim + 1.
      * @param data Record data.
      * @return An SmsMessage representing the record.
-     * 
+     *
+     * @deprecated Use android.telephony.SmsMessage.
      * @hide
      */
+    @Deprecated
     public static SmsMessage createFromEfRecord(int index, byte[] data) {
-        try {
-            SmsMessage msg = new SmsMessage();
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-            msg.indexOnSim = index;
-
-            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
-            // or STORED_UNSENT
-            // See TS 51.011 10.5.3
-            if ((data[0] & 1) == 0) {
-                Log.w(LOG_TAG,
-                        "SMS parsing failed: Trying to parse a free record");
-                return null;
-            } else {
-                msg.statusOnSim = data[0] & 0x07;
-            }
-
-            int size = data.length - 1;
-
-            // Note: Data may include trailing FF's.  That's OK; message
-            // should still parse correctly.
-            byte[] pdu = new byte[size];
-            System.arraycopy(data, 1, pdu, 0, size);
-            msg.parsePdu(pdu);
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
-            return null;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
+                    index, data);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord(
+                    index, data);
         }
+
+        return new SmsMessage(wrappedMessage);
     }
 
     /**
      * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
      * length in bytes (not hex chars) less the SMSC header
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static int getTPLayerLengthForPDU(String pdu) {
-        int len = pdu.length() / 2;
-        int smscLen = 0;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        smscLen = Integer.parseInt(pdu.substring(0, 2), 16);
-
-        return len - smscLen - 1;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu);
+        } else {
+            return com.android.internal.telephony.gsm.SmsMessage.getTPLayerLengthForPDU(pdu);
+        }
     }
 
     /**
@@ -466,7 +292,9 @@
      *         the number of code units used, and int[2] is the number of code
      *         units remaining until the next message. int[3] is the encoding
      *         type that should be used for the message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static int[] calculateLength(CharSequence messageBody, boolean use7bitOnly) {
         int ret[] = new int[4];
 
@@ -517,10 +345,10 @@
      *         units remaining until the next message. int[3] is the encoding
      *         type that should be used for the message.
      */
+    @Deprecated
     public static int[] calculateLength(String messageBody, boolean use7bitOnly) {
         return calculateLength((CharSequence)messageBody, use7bitOnly);
     }
-    
 
     /**
      * Get an SMS-SUBMIT PDU for a destination address and a message
@@ -529,92 +357,27 @@
      * @return a <code>SubmitPdu</code> containing the encoded SC
      *         address, if applicable, and the encoded message.
      *         Returns null on encode error.
+     * @deprecated Use android.telephony.SmsMessage.
      * @hide
      */
+    @Deprecated
     public static SubmitPdu getSubmitPdu(String scAddress,
             String destinationAddress, String message,
             boolean statusReportRequested, byte[] header) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        // Perform null parameter checks.
-        if (message == null || destinationAddress == null) {
-            return null;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
         }
 
-        SubmitPdu ret = new SubmitPdu();
-        // MTI = SMS-SUBMIT, UDHI = header != null
-        byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00));
-        ByteArrayOutputStream bo = getSubmitPduHead(
-                scAddress, destinationAddress, mtiByte,
-                statusReportRequested, ret);
-
-        try {
-            // First, try encoding it with the GSM alphabet
-
-            // User Data (and length)
-            byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header);
-
-            if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) {
-                // Message too long
-                return null;
-            }
-
-            // TP-Data-Coding-Scheme
-            // Default encoding, uncompressed
-            // To test writing messages to the SIM card, change this value 0x00 to 0x12, which
-            // means "bits 1 and 0 contain message class, and the class is 2". Note that this
-            // takes effect for the sender. In other words, messages sent by the phone with this
-            // change will end up on the receiver's SIM card. You can then send messages to
-            // yourself (on a phone with this change) and they'll end up on the SIM card.
-            bo.write(0x00); 
-
-            // (no TP-Validity-Period)
-
-            bo.write(userData, 0, userData.length);
-        } catch (EncodeException ex) {
-            byte[] userData, textPart;
-            // Encoding to the 7-bit alphabet failed. Let's see if we can
-            // send it as a UCS-2 encoded message
-
-            try {
-                textPart = message.getBytes("utf-16be");
-            } catch (UnsupportedEncodingException uex) {
-                Log.e(LOG_TAG,
-                      "Implausible UnsupportedEncodingException ",
-                      uex);
-                return null;
-            }
-            
-            if (header != null) {
-                userData = new byte[header.length + textPart.length];
-                
-                System.arraycopy(header, 0, userData, 0, header.length);
-                System.arraycopy(textPart, 0, userData, header.length, textPart.length);
-            } else {
-                userData = textPart;
-            }
-
-            if (userData.length > MAX_USER_DATA_BYTES) {
-                // Message too long
-                return null;
-            }
-
-            // TP-Data-Coding-Scheme
-            // Class 3, UCS-2 encoding, uncompressed
-            bo.write(0x0b);
-
-            // (no TP-Validity-Period)
-            
-            // TP-UDL
-            bo.write(userData.length);
-
-            bo.write(userData, 0, userData.length);
-        }
-
-        ret.encodedMessage = bo.toByteArray();
-        return ret;
+        return new SubmitPdu(spb);
     }
 
-
     /**
      * Get an SMS-SUBMIT PDU for a destination address and a message
      *
@@ -622,12 +385,23 @@
      * @return a <code>SubmitPdu</code> containing the encoded SC
      *         address, if applicable, and the encoded message.
      *         Returns null on encode error.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static SubmitPdu getSubmitPdu(String scAddress,
-            String destinationAddress, String message,
-            boolean statusReportRequested) {
+            String destinationAddress, String message, boolean statusReportRequested) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
     }
 
     /**
@@ -641,478 +415,105 @@
      * @return a <code>SubmitPdu</code> containing the encoded SC
      *         address, if applicable, and the encoded message.
      *         Returns null on encode error.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static SubmitPdu getSubmitPdu(String scAddress,
             String destinationAddress, short destinationPort, byte[] data,
             boolean statusReportRequested) {
-        if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) {
-            Log.e(LOG_TAG, "SMS data message may only contain "
-                    + (MAX_USER_DATA_BYTES - 7) + " bytes");
-            return null;
-        }
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        SubmitPdu ret = new SubmitPdu();
-        ByteArrayOutputStream bo = getSubmitPduHead(
-                scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT,
-                                                            // TP-UDHI = true
-                statusReportRequested, ret);
-
-        // TP-Data-Coding-Scheme
-        // No class, 8 bit data
-        bo.write(0x04);
-
-        // (no TP-Validity-Period)
-
-        // User data size
-        bo.write(data.length + 7);
-
-        // User data header size
-        bo.write(0x06); // header is 6 octets
-
-        // User data header, indicating the destination port
-        bo.write(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT); // port
-                                                                // addressing
-                                                                // header
-        bo.write(0x04); // each port is 2 octets
-        bo.write((destinationPort >> 8) & 0xFF); // MSB of destination port
-        bo.write(destinationPort & 0xFF); // LSB of destination port
-        bo.write(0x00); // MSB of originating port
-        bo.write(0x00); // LSB of originating port
-
-        // User data
-        bo.write(data, 0, data.length);
-
-        ret.encodedMessage = bo.toByteArray();
-        return ret;
-    }
-
-    /**
-     * Create the beginning of a SUBMIT PDU.  This is the part of the
-     * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu},
-     * one of which takes a byte array and the other of which takes a
-     * <code>String</code>.
-     *
-     * @param scAddress Service Centre address. null == use default
-     * @param destinationAddress the address of the destination for the message
-     * @param mtiByte
-     * @param ret <code>SubmitPdu</code> containing the encoded SC
-     *        address, if applicable, and the encoded message
-     */
-    private static ByteArrayOutputStream getSubmitPduHead(
-            String scAddress, String destinationAddress, byte mtiByte,
-            boolean statusReportRequested, SubmitPdu ret) {
-        ByteArrayOutputStream bo = new ByteArrayOutputStream(
-                MAX_USER_DATA_BYTES + 40);
-
-        // SMSC address with length octet, or 0
-        if (scAddress == null) {
-            ret.encodedScAddress = null;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
         } else {
-            ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(
-                    scAddress);
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
         }
 
-        // TP-Message-Type-Indicator (and friends)
-        if (statusReportRequested) {
-            // Set TP-Status-Report-Request bit.
-            mtiByte |= 0x20;
-            if (Config.LOGD) Log.d(LOG_TAG, "SMS status report requested");
-        }
-        bo.write(mtiByte);
-
-        // space for TP-Message-Reference
-        bo.write(0);
-
-        byte[] daBytes;
-
-        daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress);
-
-        // destination address length in BCD digits, ignoring TON byte and pad
-        // TODO Should be better.
-        bo.write((daBytes.length - 1) * 2
-                - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0));
-
-        // destination address
-        bo.write(daBytes, 0, daBytes.length);
-
-        // TP-Protocol-Identifier
-        bo.write(0);
-        return bo;
-    }
-
-    static class PduParser {
-        byte pdu[];
-
-        int cur;
-
-        SmsHeader userDataHeader;
-
-        byte[] userData;
-
-        int mUserDataSeptetPadding;
-
-        int mUserDataSize;
-
-        PduParser(String s) {
-            this(SimUtils.hexStringToBytes(s));
-        }
-
-        PduParser(byte[] pdu) {
-            this.pdu = pdu;
-            cur = 0;
-            mUserDataSeptetPadding = 0;
-        }
-
-        /**
-         * Parse and return the SC address prepended to SMS messages coming via
-         * the TS 27.005 / AT interface.  Returns null on invalid address
-         */
-        String getSCAddress() {
-            int len;
-            String ret;
-
-            // length of SC Address
-            len = getByte();
-
-            if (len == 0) {
-                // no SC address
-                ret = null;
-            } else {
-                // SC address
-                try {
-                    ret = PhoneNumberUtils
-                            .calledPartyBCDToString(pdu, cur, len);
-                } catch (RuntimeException tr) {
-                    Log.d(LOG_TAG, "invalid SC address: ", tr);
-                    ret = null;
-                }
-            }
-
-            cur += len;
-
-            return ret;
-        }
-
-        /**
-         * returns non-sign-extended byte value
-         */
-        int getByte() {
-            return pdu[cur++] & 0xff;
-        }
-
-        /**
-         * Any address except the SC address (eg, originating address) See TS
-         * 23.040 9.1.2.5
-         */
-        SmsAddress getAddress() {
-            SmsAddress ret;
-
-            // "The Address-Length field is an integer representation of
-            // the number field, i.e. excludes any semi octet containing only
-            // fill bits."
-            // The TOA field is not included as part of this
-            int addressLength = pdu[cur] & 0xff;
-            int lengthBytes = 2 + (addressLength + 1) / 2;
-
-            ret = new SmsAddress(pdu, cur, lengthBytes);
-
-            cur += lengthBytes;
-
-            return ret;
-        }
-
-        /**
-         * Parses an SC timestamp and returns a currentTimeMillis()-style
-         * timestamp
-         */
-
-        long getSCTimestampMillis() {
-            // TP-Service-Centre-Time-Stamp
-            int year = SimUtils.bcdByteToInt(pdu[cur++]);
-            int month = SimUtils.bcdByteToInt(pdu[cur++]);
-            int day = SimUtils.bcdByteToInt(pdu[cur++]);
-            int hour = SimUtils.bcdByteToInt(pdu[cur++]);
-            int minute = SimUtils.bcdByteToInt(pdu[cur++]);
-            int second = SimUtils.bcdByteToInt(pdu[cur++]);
-
-            // For the timezone, the most significant bit of the
-            // least signficant nibble is the sign byte
-            // (meaning the max range of this field is 79 quarter-hours,
-            // which is more than enough)
-
-            byte tzByte = pdu[cur++];
-
-            // Mask out sign bit.
-            int timezoneOffset = SimUtils
-                    .bcdByteToInt((byte) (tzByte & (~0x08)));
-
-            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset
-                    : -timezoneOffset;
-
-            Time time = new Time(Time.TIMEZONE_UTC);
-
-            // It's 2006.  Should I really support years < 2000?
-            time.year = year >= 90 ? year + 1900 : year + 2000;
-            time.month = month - 1;
-            time.monthDay = day;
-            time.hour = hour;
-            time.minute = minute;
-            time.second = second;
-
-            // Timezone offset is in quarter hours.
-            return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000);
-        }
-
-        /**
-         * Pulls the user data out of the PDU, and separates the payload from
-         * the header if there is one.
-         *
-         * @param hasUserDataHeader true if there is a user data header
-         * @param dataInSeptets true if the data payload is in septets instead
-         *  of octets
-         * @return the number of septets or octets in the user data payload
-         */
-        int constructUserData(boolean hasUserDataHeader, boolean dataInSeptets)
-        {
-            int offset = cur;
-            int userDataLength = pdu[offset++] & 0xff;
-            int headerSeptets = 0;
-
-            if (hasUserDataHeader) {
-                int userDataHeaderLength = pdu[offset++] & 0xff;
-
-                byte[] udh = new byte[userDataHeaderLength];
-                System.arraycopy(pdu, offset, udh, 0, userDataHeaderLength);
-                userDataHeader = SmsHeader.parse(udh);
-                offset += userDataHeaderLength;
-
-                int headerBits = (userDataHeaderLength + 1) * 8;
-                headerSeptets = headerBits / 7;
-                headerSeptets += (headerBits % 7) > 0 ? 1 : 0;
-                mUserDataSeptetPadding = (headerSeptets * 7) - headerBits;
-            }
-
-            /*
-             * Here we just create the user data length to be the remainder of
-             * the pdu minus the user data hearder. This is because the count
-             * could mean the number of uncompressed sepets if the userdata is
-             * encoded in 7-bit.
-             */
-            userData = new byte[pdu.length - offset];
-            System.arraycopy(pdu, offset, userData, 0, userData.length);
-            cur = offset;
-
-            if (dataInSeptets) {
-                // Return the number of septets
-                int count = userDataLength - headerSeptets;
-                // If count < 0, return 0 (means UDL was probably incorrect)
-                return count < 0 ? 0 : count;
-            } else {
-                // Return the number of octets
-                return userData.length;
-            }
-        }
-
-        /**
-         * Returns the user data payload, not including the headers
-         *
-         * @return the user data payload, not including the headers
-         */
-        byte[] getUserData() {
-            return userData;
-        }
-
-        /**
-         * Returns the number of padding bits at the begining of the user data
-         * array before the start of the septets.
-         *
-         * @return the number of padding bits at the begining of the user data
-         * array before the start of the septets
-         */
-        int getUserDataSeptetPadding() {
-            return mUserDataSeptetPadding;
-        }
-
-        /**
-         * Returns an object representing the user data headers
-         *
-         * @return an object representing the user data headers
-         * 
-         * {@hide}
-         */
-        SmsHeader getUserDataHeader() {
-            return userDataHeader;
-        }
-
-/*
-        XXX Not sure what this one is supposed to be doing, and no one is using
-        it.
-        String getUserDataGSM8bit() {
-            // System.out.println("remainder of pud:" +
-            // HexDump.dumpHexString(pdu, cur, pdu.length - cur));
-            int count = pdu[cur++] & 0xff;
-            int size = pdu[cur++];
-
-            // skip over header for now
-            cur += size;
-
-            if (pdu[cur - 1] == 0x01) {
-                int tid = pdu[cur++] & 0xff;
-                int type = pdu[cur++] & 0xff;
-
-                size = pdu[cur++] & 0xff;
-
-                int i = cur;
-
-                while (pdu[i++] != '\0') {
-                }
-
-                int length = i - cur;
-                String mimeType = new String(pdu, cur, length);
-
-                cur += length;
-
-                if (false) {
-                    System.out.println("tid = 0x" + HexDump.toHexString(tid));
-                    System.out.println("type = 0x" + HexDump.toHexString(type));
-                    System.out.println("header size = " + size);
-                    System.out.println("mimeType = " + mimeType);
-                    System.out.println("remainder of header:" +
-                     HexDump.dumpHexString(pdu, cur, (size - mimeType.length())));
-                }
-
-                cur += size - mimeType.length();
-
-                // System.out.println("data count = " + count + " cur = " + cur
-                // + " :" + HexDump.dumpHexString(pdu, cur, pdu.length - cur));
-
-                MMSMessage msg = MMSMessage.parseEncoding(mContext, pdu, cur,
-                        pdu.length - cur);
-            } else {
-                System.out.println(new String(pdu, cur, pdu.length - cur - 1));
-            }
-
-            return SimUtils.bytesToHexString(pdu);
-        }
-*/
-
-        /**
-         * Interprets the user data payload as pack GSM 7bit characters, and
-         * decodes them into a String.
-         *
-         * @param septetCount the number of septets in the user data payload
-         * @return a String with the decoded characters
-         */
-        String getUserDataGSM7Bit(int septetCount) {
-            String ret;
-
-            ret = GsmAlphabet.gsm7BitPackedToString(pdu, cur, septetCount,
-                    mUserDataSeptetPadding);
-
-            cur += (septetCount * 7) / 8;
-
-            return ret;
-        }
-
-        /**
-         * Interprets the user data payload as UCS2 characters, and
-         * decodes them into a String.
-         *
-         * @param byteCount the number of bytes in the user data payload
-         * @return a String with the decoded characters
-         */
-        String getUserDataUCS2(int byteCount) {
-            String ret;
-
-            try {
-                ret = new String(pdu, cur, byteCount, "utf-16");
-            } catch (UnsupportedEncodingException ex) {
-                ret = "";
-                Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex);
-            }
-
-            cur += byteCount;
-            return ret;
-        }
-
-        boolean moreDataPresent() {
-            return (pdu.length > cur);
-        }
+        return new SubmitPdu(spb);
     }
 
     /**
      * Returns the address of the SMS service center that relayed this message
      * or null if there is none.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getServiceCenterAddress() {
-        return scAddress;
+        return mWrappedSmsMessage.getServiceCenterAddress();
     }
 
     /**
      * Returns the originating address (sender) of this SMS message in String
      * form or null if unavailable
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getOriginatingAddress() {
-        if (originatingAddress == null) {
-            return null;
-        }
-
-        return originatingAddress.getAddressString();
+        return mWrappedSmsMessage.getOriginatingAddress();
     }
 
     /**
      * Returns the originating address, or email from address if this message
      * was from an email gateway. Returns null if originating address
      * unavailable.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getDisplayOriginatingAddress() {
-        if (isEmail) {
-            return emailFrom;
-        } else {
-            return getOriginatingAddress();
-        }
+        return mWrappedSmsMessage.getDisplayOriginatingAddress();
     }
 
     /**
      * Returns the message body as a String, if it exists and is text based.
      * @return message body is there is one, otherwise null
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getMessageBody() {
-        return messageBody;
+        return mWrappedSmsMessage.getMessageBody();
     }
 
     /**
      * Returns the class of this message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public MessageClass getMessageClass() {
-        return messageClass;
+        int index = mWrappedSmsMessage.getMessageClass().ordinal();
+
+        return MessageClass.values()[index];
     }
 
     /**
      * Returns the message body, or email message body if this message was from
      * an email gateway. Returns null if message body unavailable.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getDisplayMessageBody() {
-        if (isEmail) {
-            return emailBody;
-        } else {
-            return getMessageBody();
-        }
+        return mWrappedSmsMessage.getDisplayMessageBody();
     }
 
     /**
      * Unofficial convention of a subject line enclosed in parens empty string
      * if not present
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getPseudoSubject() {
-        return pseudoSubject == null ? "" : pseudoSubject;
+        return mWrappedSmsMessage.getPseudoSubject();
     }
 
     /**
      * Returns the service centre timestamp in currentTimeMillis() format
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public long getTimestampMillis() {
-        return scTimeMillis;
+        return mWrappedSmsMessage.getTimestampMillis();
     }
 
     /**
@@ -1120,129 +521,114 @@
      *
      * @return true if this message came through an email gateway and email
      *         sender / subject / parsed body are available
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isEmail() {
-        return isEmail;
+        return mWrappedSmsMessage.isEmail();
     }
 
-    /**
+     /**
      * @return if isEmail() is true, body of the email sent through the gateway.
      *         null otherwise
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getEmailBody() {
-        return emailBody;
+        return mWrappedSmsMessage.getEmailBody();
     }
 
     /**
      * @return if isEmail() is true, email from address of email sent through
      *         the gateway. null otherwise
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getEmailFrom() {
-        return emailFrom;
+        return mWrappedSmsMessage.getEmailFrom();
     }
 
     /**
      * Get protocol identifier.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public int getProtocolIdentifier() {
-        return protocolIdentifier;
+        return mWrappedSmsMessage.getProtocolIdentifier();
     }
 
     /**
-     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
-     * SMS
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message" SMS
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isReplace() {
-        return (protocolIdentifier & 0xc0) == 0x40
-                && (protocolIdentifier & 0x3f) > 0
-                && (protocolIdentifier & 0x3f) < 8;
+        return mWrappedSmsMessage.isReplace();
     }
 
     /**
      * Returns true for CPHS MWI toggle message.
      *
-     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
-     *         B.4.2
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section B.4.2
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isCphsMwiMessage() {
-        return originatingAddress.isCphsVoiceMessageClear()
-                || originatingAddress.isCphsVoiceMessageSet();
+        return mWrappedSmsMessage.isCphsMwiMessage();
     }
 
     /**
      * returns true if this message is a CPHS voicemail / message waiting
      * indicator (MWI) clear message
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isMWIClearMessage() {
-        if (isMwi && (mwiSense == false)) {
-            return true;
-        }
-
-        return originatingAddress != null
-                && originatingAddress.isCphsVoiceMessageClear();
+        return mWrappedSmsMessage.isMWIClearMessage();
     }
 
     /**
      * returns true if this message is a CPHS voicemail / message waiting
      * indicator (MWI) set message
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isMWISetMessage() {
-        if (isMwi && (mwiSense == true)) {
-            return true;
-        }
-
-        return originatingAddress != null
-                && originatingAddress.isCphsVoiceMessageSet();
+        return mWrappedSmsMessage.isMWISetMessage();
     }
 
     /**
      * returns true if this message is a "Message Waiting Indication Group:
      * Discard Message" notification and should not be stored.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isMwiDontStore() {
-        if (isMwi && mwiDontStore) {
-            return true;
-        }
-
-        if (isCphsMwiMessage()) {
-            // See CPHS 4.2 Section B.4.2.1
-            // If the user data is a single space char, do not store
-            // the message. Otherwise, store and display as usual
-            if (" ".equals(getMessageBody())) {
-                ;
-            }
-            return true;
-        }
-
-        return false;
+        return mWrappedSmsMessage.isMwiDontStore();
     }
 
     /**
-     * returns the user data section minus the user data header if one was
-     * present.
+     * returns the user data section minus the user data header if one was present.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public byte[] getUserData() {
-        return userData;
+        return mWrappedSmsMessage.getUserData();
     }
 
-    /**
-     * Returns an object representing the user data header
-     *
-     * @return an object representing the user data header
-     * 
-     * {@hide}
-     */
-    public SmsHeader getUserDataHeader() {
-        return userDataHeader;
-    }
+    /* Not part of the SDK interface and only needed by specific classes:
+       protected SmsHeader getUserDataHeader()
+    */
 
     /**
      * Returns the raw PDU for the message.
      *
      * @return the raw PDU for the message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public byte[] getPdu() {
-        return mPdu;
+        return mWrappedSmsMessage.getPdu();
     }
 
     /**
@@ -1254,369 +640,108 @@
      *         SmsManager.STATUS_ON_SIM_UNREAD
      *         SmsManager.STATUS_ON_SIM_SEND
      *         SmsManager.STATUS_ON_SIM_UNSENT
+     * @deprecated Use android.telephony.SmsMessage and getStatusOnIcc instead.
      */
+    @Deprecated
     public int getStatusOnSim() {
-        return statusOnSim;
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     * @deprecated Use android.telephony.SmsMessage.
+     * @hide
+     */
+    @Deprecated
+    public int getStatusOnIcc() {
+
+        return mWrappedSmsMessage.getStatusOnIcc();
     }
 
     /**
      * Returns the record index of the message on the SIM (1-based index).
      * @return the record index of the message on the SIM, or -1 if this
      *         SmsMessage was not created from a SIM SMS EF record.
+     * @deprecated Use android.telephony.SmsMessage and getIndexOnIcc instead.
      */
+    @Deprecated
     public int getIndexOnSim() {
-        return indexOnSim;
+        return mWrappedSmsMessage.getIndexOnIcc();
     }
 
     /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     * @deprecated Use android.telephony.SmsMessage.
+     * @hide
+     */
+    @Deprecated
+    public int getIndexOnIcc() {
+
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * GSM:
      * For an SMS-STATUS-REPORT message, this returns the status field from
-     * the status report.  This field indicates the status of a previousely
+     * the status report.  This field indicates the status of a previously
      * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
      * description of values.
+     * CDMA:
+     * For not interfering with status codes from GSM, the value is
+     * shifted to the bits 31-16.
+     * The value is composed of an error class (bits 25-24) and a status code (bits 23-16).
+     * Possible codes are described in C.S0015-B, v2.0, 4.5.21.
      *
      * @return 0 indicates the previously sent message was received.
-     *         See TS 23.040, 9.9.2.3.15 for a description of other possible
-     *         values.
+     *         See TS 23.040, 9.9.2.3.15 and C.S0015-B, v2.0, 4.5.21
+     *         for a description of other possible values.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public int getStatus() {
-        return status;
+        return mWrappedSmsMessage.getStatus();
     }
 
     /**
      * Return true iff the message is a SMS-STATUS-REPORT message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isStatusReportMessage() {
-        return isStatusReportMessage;
+        return mWrappedSmsMessage.isStatusReportMessage();
     }
 
     /**
      * Returns true iff the <code>TP-Reply-Path</code> bit is set in
      * this message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isReplyPathPresent() {
-        return replyPathPresent;
+        return mWrappedSmsMessage.isReplyPathPresent();
     }
 
-    /**
-     * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6]
-     * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format:
-     * ME/TA converts each octet of TP data unit into two IRA character long
-     * hexad number (e.g. octet with integer value 42 is presented to TE as two
-     * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast,
-     * something else...
+    /** This method returns the reference to a specific
+     *  SmsMessage object, which is used for accessing its static methods.
+     * @return Specific SmsMessage.
+     * @deprecated Use android.telephony.SmsMessage.
      */
-    private void parsePdu(byte[] pdu) {
-        mPdu = pdu;
-        // Log.d(LOG_TAG, "raw sms mesage:");
-        // Log.d(LOG_TAG, s);
-
-        PduParser p = new PduParser(pdu);
-
-        scAddress = p.getSCAddress();
-
-        if (scAddress != null) {
-            if (Config.LOGD) Log.d(LOG_TAG, "SMS SC address: " + scAddress);
-        }
-
-        // TODO(mkf) support reply path, user data header indicator
-
-        // TP-Message-Type-Indicator
-        // 9.2.3
-        int firstByte = p.getByte();
-
-        mti = firstByte & 0x3;
-        switch (mti) {
-        // TP-Message-Type-Indicator
-        // 9.2.3
-        case 0:
-            parseSmsDeliver(p, firstByte);
-            break;
-        case 2:
-            parseSmsStatusReport(p, firstByte);
-            break;
-        default:
-            // TODO(mkf) the rest of these
-            throw new RuntimeException("Unsupported message type");
-        }
-    }
-
-    /**
-     * Parses a SMS-STATUS-REPORT message.
-     *
-     * @param p A PduParser, cued past the first byte.
-     * @param firstByte The first byte of the PDU, which contains MTI, etc.
-     */
-    private void parseSmsStatusReport(PduParser p, int firstByte) {
-        isStatusReportMessage = true;
-
-        // TP-Status-Report-Qualifier bit == 0 for SUBMIT
-        forSubmit = (firstByte & 0x20) == 0x00;
-        // TP-Message-Reference
-        messageRef = p.getByte();
-        // TP-Recipient-Address
-        recipientAddress = p.getAddress();
-        // TP-Service-Centre-Time-Stamp
-        scTimeMillis = p.getSCTimestampMillis();
-        // TP-Discharge-Time
-        dischargeTimeMillis = p.getSCTimestampMillis();
-        // TP-Status
-        status = p.getByte();
-
-        // The following are optional fields that may or may not be present.
-        if (p.moreDataPresent()) {
-            // TP-Parameter-Indicator
-            int extraParams = p.getByte();
-            int moreExtraParams = extraParams;
-            while ((moreExtraParams & 0x80) != 0) {
-                // We only know how to parse a few extra parameters, all
-                // indicated in the first TP-PI octet, so skip over any
-                // additional TP-PI octets.
-                moreExtraParams = p.getByte();
-            }
-            // TP-Protocol-Identifier
-            if ((extraParams & 0x01) != 0) {
-                protocolIdentifier = p.getByte();
-            }
-            // TP-Data-Coding-Scheme
-            if ((extraParams & 0x02) != 0) {
-                dataCodingScheme = p.getByte();
-            }
-            // TP-User-Data-Length (implies existence of TP-User-Data)
-            if ((extraParams & 0x04) != 0) {
-                boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
-                parseUserData(p, hasUserDataHeader);
-            }
-        }
-    }
-
-    private void parseSmsDeliver(PduParser p, int firstByte) {
-        replyPathPresent = (firstByte & 0x80) == 0x80;
-
-        originatingAddress = p.getAddress();
-
-        if (originatingAddress != null) {
-            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
-                    + originatingAddress.address);
-        }
-
-        // TP-Protocol-Identifier (TP-PID)
-        // TS 23.040 9.2.3.9
-        protocolIdentifier = p.getByte();
-
-        // TP-Data-Coding-Scheme
-        // see TS 23.038
-        dataCodingScheme = p.getByte();
-
-        if (Config.LOGV) {
-            Log.v(LOG_TAG, "SMS TP-PID:" + protocolIdentifier
-                    + " data coding scheme: " + dataCodingScheme);
-        }
-
-        scTimeMillis = p.getSCTimestampMillis();
-
-        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
-
-        boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
-
-        parseUserData(p, hasUserDataHeader);
-    }
-
-    /**
-     * Parses the User Data of an SMS.
-     *
-     * @param p The current PduParser.
-     * @param hasUserDataHeader Indicates whether a header is present in the
-     *                          User Data.
-     */
-    private void parseUserData(PduParser p, boolean hasUserDataHeader) {
-        boolean hasMessageClass = false;
-        boolean userDataCompressed = false;
-
-        int encodingType = ENCODING_UNKNOWN;
-
-        // Look up the data encoding scheme
-        if ((dataCodingScheme & 0x80) == 0) {
-            // Bits 7..4 == 0xxx
-            automaticDeletion = (0 != (dataCodingScheme & 0x40));
-            userDataCompressed = (0 != (dataCodingScheme & 0x20));
-            hasMessageClass = (0 != (dataCodingScheme & 0x10));
-
-            if (userDataCompressed) {
-                Log.w(LOG_TAG, "4 - Unsupported SMS data coding scheme "
-                        + "(compression) " + (dataCodingScheme & 0xff));
-            } else {
-                switch ((dataCodingScheme >> 2) & 0x3) {
-                case 0: // GSM 7 bit default alphabet
-                    encodingType = ENCODING_7BIT;
-                    break;
-
-                case 2: // UCS 2 (16bit)
-                    encodingType = ENCODING_16BIT;
-                    break;
-
-                case 1: // 8 bit data
-                case 3: // reserved
-                    Log.w(LOG_TAG, "1 - Unsupported SMS data coding scheme "
-                            + (dataCodingScheme & 0xff));
-                    encodingType = ENCODING_8BIT;
-                    break;
-                }
-            }
-        } else if ((dataCodingScheme & 0xf0) == 0xf0) {
-            automaticDeletion = false;
-            hasMessageClass = true;
-            userDataCompressed = false;
-
-            if (0 == (dataCodingScheme & 0x04)) {
-                // GSM 7 bit default alphabet
-                encodingType = ENCODING_7BIT;
-            } else {
-                // 8 bit data
-                encodingType = ENCODING_8BIT;
-            }
-        } else if ((dataCodingScheme & 0xF0) == 0xC0
-                || (dataCodingScheme & 0xF0) == 0xD0
-                || (dataCodingScheme & 0xF0) == 0xE0) {
-            // 3GPP TS 23.038 V7.0.0 (2006-03) section 4
-
-            // 0xC0 == 7 bit, don't store
-            // 0xD0 == 7 bit, store
-            // 0xE0 == UCS-2, store
-
-            if ((dataCodingScheme & 0xF0) == 0xE0) {
-                encodingType = ENCODING_16BIT;
-            } else {
-                encodingType = ENCODING_7BIT;
-            }
-
-            userDataCompressed = false;
-            boolean active = ((dataCodingScheme & 0x08) == 0x08);
-
-            // bit 0x04 reserved
-
-            if ((dataCodingScheme & 0x03) == 0x00) {
-                isMwi = true;
-                mwiSense = active;
-                mwiDontStore = ((dataCodingScheme & 0xF0) == 0xC0);
-            } else {
-                isMwi = false;
-
-                Log.w(LOG_TAG, "MWI for fax, email, or other "
-                        + (dataCodingScheme & 0xff));
-            }
+    private static final SmsMessageBase getSmsFacility(){
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return new com.android.internal.telephony.cdma.SmsMessage();
         } else {
-            Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme "
-                    + (dataCodingScheme & 0xff));
-        }
-
-        // set both the user data and the user data header.
-        int count = p.constructUserData(hasUserDataHeader,
-                encodingType == ENCODING_7BIT);
-        this.userData = p.getUserData();
-        this.userDataHeader = p.getUserDataHeader();
-
-        switch (encodingType) {
-        case ENCODING_UNKNOWN:
-        case ENCODING_8BIT:
-            messageBody = null;
-            break;
-
-        case ENCODING_7BIT:
-            messageBody = p.getUserDataGSM7Bit(count);
-            break;
-
-        case ENCODING_16BIT:
-            messageBody = p.getUserDataUCS2(count);
-            break;
-        }
-
-        if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'");
-
-        if (messageBody != null) {
-            parseMessageBody();
-        }
-
-        if (!hasMessageClass) {
-            messageClass = MessageClass.UNKNOWN;
-        } else {
-            switch (dataCodingScheme & 0x3) {
-            case 0:
-                messageClass = MessageClass.CLASS_0;
-                break;
-            case 1:
-                messageClass = MessageClass.CLASS_1;
-                break;
-            case 2:
-                messageClass = MessageClass.CLASS_2;
-                break;
-            case 3:
-                messageClass = MessageClass.CLASS_3;
-                break;
-            }
+            return new com.android.internal.telephony.gsm.SmsMessage();
         }
     }
-
-    private void parseMessageBody() {
-        if (originatingAddress.couldBeEmailGateway()) {
-            extractEmailAddressFromMessageBody();
-        }
-    }
-
-    /**
-     * Try to parse this message as an email gateway message -> Neither
-     * of the standard ways are currently supported: There are two ways
-     * specified in TS 23.040 Section 3.8 (not supported via this mechanism) -
-     * SMS message "may have its TP-PID set for internet electronic mail - MT
-     * SMS format: [<from-address><space>]<message> - "Depending on the
-     * nature of the gateway, the destination/origination address is either
-     * derived from the content of the SMS TP-OA or TP-DA field, or the
-     * TP-OA/TP-DA field contains a generic gateway address and the to/from
-     * address is added at the beginning as shown above." - multiple addreses
-     * separated by commas, no spaces - subject field delimited by '()' or '##'
-     * and '#' Section 9.2.3.24.11
-     */
-    private void extractEmailAddressFromMessageBody() {
-
-        /*
-         * a little guesswork here. I haven't found doc for this.
-         * the format could be either
-         *
-         * 1. [x@y][ ]/[subject][ ]/[body]
-         * -or-
-         * 2. [x@y][ ]/[body]
-         */
-        int slash = 0, slash2 = 0, atSymbol = 0;
-
-        try {
-            slash = messageBody.indexOf(" /");
-            if (slash == -1) {
-                return;
-            }
-
-            atSymbol = messageBody.indexOf('@');
-            if (atSymbol == -1 || atSymbol > slash) {
-                return;
-            }
-
-            emailFrom = messageBody.substring(0, slash);
-
-            slash2 = messageBody.indexOf(" /", slash + 2);
-
-            if (slash2 == -1) {
-                pseudoSubject = null;
-                emailBody = messageBody.substring(slash + 2);
-            } else {
-                pseudoSubject = messageBody.substring(slash + 2, slash2);
-                emailBody = messageBody.substring(slash2 + 2);
-            }
-
-            isEmail = true;
-        } catch (Exception ex) {
-            Log.w(LOG_TAG,
-                    "extractEmailAddressFromMessageBody: exception slash="
-                    + slash + ", atSymbol=" + atSymbol + ", slash2="
-                    + slash2, ex);
-        }
-    }
-
 }
+
diff --git a/telephony/java/com/android/internal/telephony/ATResponseParser.java b/telephony/java/com/android/internal/telephony/ATResponseParser.java
index 93ec455..fdb0526 100644
--- a/telephony/java/com/android/internal/telephony/ATResponseParser.java
+++ b/telephony/java/com/android/internal/telephony/ATResponseParser.java
@@ -34,7 +34,7 @@
     {
         this.line = line;
     }
-    
+
     public boolean
     nextBoolean()
     {
@@ -147,7 +147,7 @@
         }
     }
 
- 
+
     /** Throws ATParseEx if whitespace extends to the end of string */
     private char
     skipWhiteSpace (char c)
diff --git a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl b/telephony/java/com/android/internal/telephony/AdnRecord.aidl
similarity index 93%
rename from telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl
rename to telephony/java/com/android/internal/telephony/AdnRecord.aidl
index 68d9a7c..b4a1a29 100644
--- a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl
+++ b/telephony/java/com/android/internal/telephony/AdnRecord.aidl
@@ -14,6 +14,7 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 parcelable AdnRecord;
+
diff --git a/telephony/java/com/android/internal/telephony/AdnRecord.java b/telephony/java/com/android/internal/telephony/AdnRecord.java
new file mode 100644
index 0000000..5f40579
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/AdnRecord.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.GsmAlphabet;
+
+
+/**
+ *
+ * Used to load or store ADNs (Abbreviated Dialing Numbers).
+ *
+ * {@hide}
+ *
+ */
+public class AdnRecord implements Parcelable {
+    static final String LOG_TAG = "GSM";
+
+    //***** Instance Variables
+
+    String alphaTag = "";
+    String number = "";
+    int extRecord = 0xff;
+    int efid;                   // or 0 if none
+    int recordNumber;           // or 0 if none
+
+
+    //***** Constants
+
+    // In an ADN record, everything but the alpha identifier
+    // is in a footer that's 14 bytes
+    static final int FOOTER_SIZE_BYTES = 14;
+
+    // Maximum size of the un-extended number field
+    static final int MAX_NUMBER_SIZE_BYTES = 11;
+
+    static final int EXT_RECORD_LENGTH_BYTES = 13;
+    static final int EXT_RECORD_TYPE_ADDITIONAL_DATA = 2;
+    static final int EXT_RECORD_TYPE_MASK = 3;
+    static final int MAX_EXT_CALLED_PARTY_LENGTH = 0xa;
+
+    // ADN offset
+    static final int ADN_BCD_NUMBER_LENGTH = 0;
+    static final int ADN_TON_AND_NPI = 1;
+    static final int ADN_DAILING_NUMBER_START = 2;
+    static final int ADN_DAILING_NUMBER_END = 11;
+    static final int ADN_CAPABILITY_ID = 12;
+    static final int ADN_EXTENSION_ID = 13;
+
+    //***** Static Methods
+
+    public static final Parcelable.Creator<AdnRecord> CREATOR
+            = new Parcelable.Creator<AdnRecord>() {
+        public AdnRecord createFromParcel(Parcel source) {
+            int efid;
+            int recordNumber;
+            String alphaTag;
+            String number;
+
+            efid = source.readInt();
+            recordNumber = source.readInt();
+            alphaTag = source.readString();
+            number = source.readString();
+
+            return new AdnRecord(efid, recordNumber, alphaTag, number);
+        }
+
+        public AdnRecord[] newArray(int size) {
+            return new AdnRecord[size];
+        }
+    };
+
+
+    //***** Constructor
+    public
+    AdnRecord (byte[] record) {
+        this(0, 0, record);
+    }
+
+    public
+    AdnRecord (int efid, int recordNumber, byte[] record) {
+        this.efid = efid;
+        this.recordNumber = recordNumber;
+        parseRecord(record);
+    }
+
+    public
+    AdnRecord (String alphaTag, String number) {
+        this(0, 0, alphaTag, number);
+    }
+
+    public
+    AdnRecord (int efid, int recordNumber, String alphaTag, String number) {
+        this.efid = efid;
+        this.recordNumber = recordNumber;
+        this.alphaTag = alphaTag;
+        this.number = number;
+    }
+
+    //***** Instance Methods
+
+    public String getAlphaTag() {
+        return alphaTag;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public String toString() {
+        return "ADN Record '" + alphaTag + "' '" + number + "'";
+    }
+
+    public boolean isEmpty() {
+        return alphaTag.equals("") && number.equals("");
+    }
+
+    public boolean hasExtendedRecord() {
+        return extRecord != 0 && extRecord != 0xff;
+    }
+
+    public boolean isEqual(AdnRecord adn) {
+        return ( alphaTag.equals(adn.getAlphaTag()) &&
+                number.equals(adn.getNumber()) );
+    }
+    //***** Parcelable Implementation
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(efid);
+        dest.writeInt(recordNumber);
+        dest.writeString(alphaTag);
+        dest.writeString(number);
+    }
+
+    /**
+     * Build adn hex byte array based on record size
+     * The format of byte array is defined in 51.011 10.5.1
+     *
+     * @param recordSize is the size X of EF record
+     * @return hex byte[recordSize] to be written to EF record
+     *          return nulll for wrong format of dialing nubmer or tag
+     */
+    public byte[] buildAdnString(int recordSize) {
+        byte[] bcdNumber;
+        byte[] byteTag;
+        byte[] adnString = null;
+        int footerOffset = recordSize - FOOTER_SIZE_BYTES;
+
+        if (number == null || number.equals("") ||
+                alphaTag == null || alphaTag.equals("")) {
+
+            Log.w(LOG_TAG, "[buildAdnString] Empty alpha tag or number");
+            adnString = new byte[recordSize];
+            for (int i = 0; i < recordSize; i++) {
+                adnString[i] = (byte) 0xFF;
+            }
+        } else if (number.length()
+                > (ADN_DAILING_NUMBER_END - ADN_DAILING_NUMBER_START + 1) * 2) {
+            Log.w(LOG_TAG,
+                    "[buildAdnString] Max length of dailing number is 20");
+        } else if (alphaTag.length() > footerOffset) {
+            Log.w(LOG_TAG,
+                    "[buildAdnString] Max length of tag is " + footerOffset);
+        } else {
+
+            adnString = new byte[recordSize];
+            for (int i = 0; i < recordSize; i++) {
+                adnString[i] = (byte) 0xFF;
+            }
+
+            bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(number);
+
+            System.arraycopy(bcdNumber, 0, adnString,
+                    footerOffset + ADN_TON_AND_NPI, bcdNumber.length);
+
+            adnString[footerOffset + ADN_BCD_NUMBER_LENGTH]
+                    = (byte) (bcdNumber.length);
+            adnString[footerOffset + ADN_CAPABILITY_ID]
+                    = (byte) 0xFF; // Capacility Id
+            adnString[footerOffset + ADN_EXTENSION_ID]
+                    = (byte) 0xFF; // Extension Record Id
+
+            byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag);
+            System.arraycopy(byteTag, 0, adnString, 0, byteTag.length);
+
+        }
+
+        return adnString;
+    }
+
+    /**
+     * See TS 51.011 10.5.10
+     */
+    public void
+    appendExtRecord (byte[] extRecord) {
+        try {
+            if (extRecord.length != EXT_RECORD_LENGTH_BYTES) {
+                return;
+            }
+
+            if ((extRecord[0] & EXT_RECORD_TYPE_MASK)
+                    != EXT_RECORD_TYPE_ADDITIONAL_DATA) {
+                return;
+            }
+
+            if ((0xff & extRecord[1]) > MAX_EXT_CALLED_PARTY_LENGTH) {
+                // invalid or empty record
+                return;
+            }
+
+            number += PhoneNumberUtils.calledPartyBCDFragmentToString(
+                                        extRecord, 2, 0xff & extRecord[1]);
+
+            // We don't support ext record chaining.
+
+        } catch (RuntimeException ex) {
+            Log.w(LOG_TAG, "Error parsing AdnRecord ext record", ex);
+        }
+    }
+
+    //***** Private Methods
+
+    /**
+     * alphaTag and number are set to null on invalid format
+     */
+    private void
+    parseRecord(byte[] record) {
+        try {
+            alphaTag = IccUtils.adnStringFieldToString(
+                            record, 0, record.length - FOOTER_SIZE_BYTES);
+
+            int footerOffset = record.length - FOOTER_SIZE_BYTES;
+
+            int numberLength = 0xff & record[footerOffset];
+
+            if (numberLength > MAX_NUMBER_SIZE_BYTES) {
+                // Invalid number length
+                number = "";
+                return;
+            }
+
+            // Please note 51.011 10.5.1:
+            //
+            // "If the Dialling Number/SSC String does not contain
+            // a dialling number, e.g. a control string deactivating
+            // a service, the TON/NPI byte shall be set to 'FF' by
+            // the ME (see note 2)."
+
+            number = PhoneNumberUtils.calledPartyBCDToString(
+                            record, footerOffset + 1, numberLength);
+
+
+            extRecord = 0xff & record[record.length - 1];
+
+        } catch (RuntimeException ex) {
+            Log.w(LOG_TAG, "Error parsing AdnRecord", ex);
+            number = "";
+            alphaTag = "";
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/AdnRecordCache.java b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
similarity index 91%
rename from telephony/java/com/android/internal/telephony/gsm/AdnRecordCache.java
rename to telephony/java/com/android/internal/telephony/AdnRecordCache.java
index 9da18e3..c270ae5 100644
--- a/telephony/java/com/android/internal/telephony/gsm/AdnRecordCache.java
+++ b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.util.SparseArray;
 import android.util.Log;
@@ -23,18 +23,18 @@
 import android.os.AsyncResult;
 import java.util.ArrayList;
 import java.util.Iterator;
+import com.android.internal.telephony.IccConstants;
 
 /**
  * {@hide}
  */
-public final class AdnRecordCache extends Handler implements SimConstants
-{
+public final class AdnRecordCache extends Handler implements IccConstants {
     //***** Instance Variables
 
-    GSMPhone phone;
+    PhoneBase phone;
 
     // Indexed by EF ID
-    SparseArray<ArrayList<AdnRecord>> adnLikeFiles 
+    SparseArray<ArrayList<AdnRecord>> adnLikeFiles
         = new SparseArray<ArrayList<AdnRecord>>();
 
     // People waiting for ADN-like files to be loaded
@@ -52,9 +52,8 @@
     //***** Constructor
 
 
-    /*package*/
-    AdnRecordCache(GSMPhone phone)
-    {
+
+    public AdnRecordCache(PhoneBase phone) {
         this.phone = phone;
     }
 
@@ -63,14 +62,12 @@
     /**
      * Called from SIMRecords.onRadioNotAvailable and SIMRecords.handleSimRefresh.
      */
-    /*package*/ void
-    reset()
-    {
+    public void reset() {
         adnLikeFiles.clear();
 
         clearWaiters();
         clearUserWriters();
-        
+
     }
 
     private void clearWaiters() {
@@ -95,29 +92,27 @@
      * @return List of AdnRecords for efid if we've already loaded them this
      * radio session, or null if we haven't
      */
-    /*package*/ ArrayList<AdnRecord>
-    getRecordsIfLoaded(int efid)
-    {
+    public ArrayList<AdnRecord>
+    getRecordsIfLoaded(int efid) {
         return adnLikeFiles.get(efid);
     }
 
     /**
-     * Returns extension ef associated with ADN-like EF or -1 if 
+     * Returns extension ef associated with ADN-like EF or -1 if
      * we don't know.
      *
      * See 3GPP TS 51.011 for this mapping
      */
     private int
-    extensionEfForEf(int efid)
-    {
+    extensionEfForEf(int efid) {
         switch (efid) {
             case EF_MBDN: return EF_EXT6;
             case EF_ADN: return EF_EXT1;
             case EF_SDN: return EF_EXT3;
             case EF_FDN: return EF_EXT2;
-            case EF_MSISDN: return EF_EXT1;          
+            case EF_MSISDN: return EF_EXT1;
             default: return -1;
-        } 
+        }
     }
 
     private void sendErrorResponse(Message response, String errString) {
@@ -138,7 +133,7 @@
      * @param response message to be posted when done
      *        response.exception hold the exception in error
      */
-    void updateAdnByIndex(int efid, AdnRecord adn, int recordIndex, String pin2,
+    public void updateAdnByIndex(int efid, AdnRecord adn, int recordIndex, String pin2,
             Message response) {
 
         int extensionEF = extensionEfForEf(efid);
@@ -174,7 +169,7 @@
      * @param response message to be posted when done
      *        response.exception hold the exception in error
      */
-    void updateAdnBySearch(int efid, AdnRecord oldAdn, AdnRecord newAdn,
+    public void updateAdnBySearch(int efid, AdnRecord oldAdn, AdnRecord newAdn,
             String pin2, Message response) {
 
         int extensionEF;
@@ -227,9 +222,8 @@
      * Responds with exception (in response) if efid is not a known ADN-like
      * record
      */
-    /*package*/ void
-    requestLoadAllAdnLike (int efid, Message response)
-    {
+    public void
+    requestLoadAllAdnLike (int efid, Message response) {
         ArrayList<Message> waiters;
         ArrayList<AdnRecord> result;
 
@@ -256,25 +250,25 @@
             waiters.add(response);
             return;
         }
-        
+
         // Start loading efid
-        
+
         waiters = new ArrayList<Message>();
         waiters.add(response);
 
         adnLikeWaiters.put(efid, waiters);
 
         int extensionEF = extensionEfForEf(efid);
-    
+
         if (extensionEF < 0) {
             // respond with error if not known ADN-like record
 
             if (response != null) {
-                AsyncResult.forMessage(response).exception 
+                AsyncResult.forMessage(response).exception
                     = new RuntimeException("EF is not known ADN-like EF:" + efid);
                 response.sendToTarget();
             }
-            
+
             return;
         }
 
@@ -285,8 +279,7 @@
     //***** Private methods
 
     private void
-    notifyWaiters(ArrayList<Message> waiters, AsyncResult ar)
-    {
+    notifyWaiters(ArrayList<Message> waiters, AsyncResult ar) {
 
         if (waiters == null) {
             return;
diff --git a/telephony/java/com/android/internal/telephony/AdnRecordLoader.java b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java
new file mode 100644
index 0000000..cfb5aaa
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import java.util.ArrayList;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+
+public class AdnRecordLoader extends Handler {
+    static String LOG_TAG;
+
+    //***** Instance Variables
+
+    PhoneBase phone;
+    int ef;
+    int extensionEF;
+    int pendingExtLoads;
+    Message userResponse;
+    String pin2;
+
+    // For "load one"
+    int recordNumber;
+
+    // for "load all"
+    ArrayList<AdnRecord> adns; // only valid after EVENT_ADN_LOAD_ALL_DONE
+
+    // Either an AdnRecord or a reference to adns depending
+    // if this is a load one or load all operation
+    Object result;
+
+    //***** Event Constants
+
+    static final int EVENT_ADN_LOAD_DONE = 1;
+    static final int EVENT_EXT_RECORD_LOAD_DONE = 2;
+    static final int EVENT_ADN_LOAD_ALL_DONE = 3;
+    static final int EVENT_EF_LINEAR_RECORD_SIZE_DONE = 4;
+    static final int EVENT_UPDATE_RECORD_DONE = 5;
+
+    //***** Constructor
+
+    public AdnRecordLoader(PhoneBase phone) {
+        // The telephony unit-test cases may create AdnRecords
+        // in secondary threads
+        super(phone.getHandler().getLooper());
+
+        this.phone = phone;
+        LOG_TAG = phone.getPhoneName();
+    }
+
+    /**
+     * Resulting AdnRecord is placed in response.obj.result
+     * or response.obj.exception is set
+     */
+    public void
+    loadFromEF(int ef, int extensionEF, int recordNumber,
+                Message response) {
+        this.ef = ef;
+        this.extensionEF = extensionEF;
+        this.recordNumber = recordNumber;
+        this.userResponse = response;
+
+        phone.mIccFileHandler.loadEFLinearFixed(
+                    ef, recordNumber,
+                    obtainMessage(EVENT_ADN_LOAD_DONE));
+
+    }
+
+
+    /**
+     * Resulting ArrayList&lt;adnRecord> is placed in response.obj.result
+     * or response.obj.exception is set
+     */
+    public void
+    loadAllFromEF(int ef, int extensionEF,
+                Message response) {
+        this.ef = ef;
+        this.extensionEF = extensionEF;
+        this.userResponse = response;
+
+        phone.mIccFileHandler.loadEFLinearFixedAll(
+                    ef,
+                    obtainMessage(EVENT_ADN_LOAD_ALL_DONE));
+
+    }
+
+    /**
+     * Write adn to a EF SIM record
+     * It will get the record size of EF record and compose hex adn array
+     * then write the hex array to EF record
+     *
+     * @param adn is set with alphaTag and phoneNubmer
+     * @param ef EF fileid
+     * @param extensionEF extension EF fileid
+     * @param recordNumber 1-based record index
+     * @param pin2 for CHV2 operations, must be null if pin2 is not needed
+     * @param response will be sent to its handler when completed
+     */
+    public void
+    updateEF(AdnRecord adn, int ef, int extensionEF, int recordNumber,
+            String pin2, Message response) {
+        this.ef = ef;
+        this.extensionEF = extensionEF;
+        this.recordNumber = recordNumber;
+        this.userResponse = response;
+        this.pin2 = pin2;
+
+        phone.mIccFileHandler.getEFLinearRecordSize( ef,
+            obtainMessage(EVENT_EF_LINEAR_RECORD_SIZE_DONE, adn));
+    }
+
+    //***** Overridden from Handler
+
+    public void
+    handleMessage(Message msg) {
+        AsyncResult ar;
+        byte data[];
+        AdnRecord adn;
+
+        try {
+            switch (msg.what) {
+                case EVENT_EF_LINEAR_RECORD_SIZE_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    adn = (AdnRecord)(ar.userObj);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("get EF record size failed",
+                                ar.exception);
+                    }
+
+                    int[] recordSize = (int[])ar.result;
+                    // recordSize is int[3] array
+                    // int[0]  is the record length
+                    // int[1]  is the total length of the EF file
+                    // int[2]  is the number of records in the EF file
+                    // So int[0] * int[2] = int[1]
+                   if (recordSize.length != 3 || recordNumber > recordSize[2]) {
+                        throw new RuntimeException("get wrong EF record size format",
+                                ar.exception);
+                    }
+
+                    data = adn.buildAdnString(recordSize[0]);
+
+                    if(data == null) {
+                        throw new RuntimeException("worong ADN format",
+                                ar.exception);
+                    }
+
+                    phone.mIccFileHandler.updateEFLinearFixed(ef, recordNumber,
+                            data, pin2, obtainMessage(EVENT_UPDATE_RECORD_DONE));
+
+                    pendingExtLoads = 1;
+
+                    break;
+                case EVENT_UPDATE_RECORD_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    if (ar.exception != null) {
+                        throw new RuntimeException("update EF adn record failed",
+                                ar.exception);
+                    }
+                    pendingExtLoads = 0;
+                    result = null;
+                    break;
+                case EVENT_ADN_LOAD_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    data = (byte[])(ar.result);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("load failed", ar.exception);
+                    }
+
+                    if (false) {
+                        Log.d(LOG_TAG,"ADN EF: 0x"
+                            + Integer.toHexString(ef)
+                            + ":" + recordNumber
+                            + "\n" + IccUtils.bytesToHexString(data));
+                    }
+
+                    adn = new AdnRecord(ef, recordNumber, data);
+                    result = adn;
+
+                    if (adn.hasExtendedRecord()) {
+                        // If we have a valid value in the ext record field,
+                        // we're not done yet: we need to read the corresponding
+                        // ext record and append it
+
+                        pendingExtLoads = 1;
+
+                        phone.mIccFileHandler.loadEFLinearFixed(
+                            extensionEF, adn.extRecord,
+                            obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
+                    }
+                break;
+
+                case EVENT_EXT_RECORD_LOAD_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    data = (byte[])(ar.result);
+                    adn = (AdnRecord)(ar.userObj);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("load failed", ar.exception);
+                    }
+
+                    Log.d(LOG_TAG,"ADN extention EF: 0x"
+                        + Integer.toHexString(extensionEF)
+                        + ":" + adn.extRecord
+                        + "\n" + IccUtils.bytesToHexString(data));
+
+                    adn.appendExtRecord(data);
+
+                    pendingExtLoads--;
+                    // result should have been set in
+                    // EVENT_ADN_LOAD_DONE or EVENT_ADN_LOAD_ALL_DONE
+                break;
+
+                case EVENT_ADN_LOAD_ALL_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    ArrayList<byte[]> datas = (ArrayList<byte[]>)(ar.result);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("load failed", ar.exception);
+                    }
+
+                    adns = new ArrayList<AdnRecord>(datas.size());
+                    result = adns;
+                    pendingExtLoads = 0;
+
+                    for(int i = 0, s = datas.size() ; i < s ; i++) {
+                        adn = new AdnRecord(ef, 1 + i, datas.get(i));
+                        adns.add(adn);
+
+                        if (adn.hasExtendedRecord()) {
+                            // If we have a valid value in the ext record field,
+                            // we're not done yet: we need to read the corresponding
+                            // ext record and append it
+
+                            pendingExtLoads++;
+
+                            phone.mIccFileHandler.loadEFLinearFixed(
+                                extensionEF, adn.extRecord,
+                                obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
+                        }
+                    }
+                break;
+            }
+        } catch (RuntimeException exc) {
+            if (userResponse != null) {
+                AsyncResult.forMessage(userResponse)
+                                .exception = exc;
+                userResponse.sendToTarget();
+                // Loading is all or nothing--either every load succeeds
+                // or we fail the whole thing.
+                userResponse = null;
+            }
+            return;
+        }
+
+        if (userResponse != null && pendingExtLoads == 0) {
+            AsyncResult.forMessage(userResponse).result
+                = result;
+
+            userResponse.sendToTarget();
+            userResponse = null;
+        }
+    }
+
+
+}
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
new file mode 100644
index 0000000..11e7461
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+
+import android.content.Context;
+import android.os.RegistrantList;
+import android.os.Registrant;
+import android.os.Handler;
+import android.os.AsyncResult;
+import android.provider.Checkin;
+import android.util.Config;
+import android.util.Log;
+
+/**
+ * {@hide}
+ */
+public abstract class BaseCommands implements CommandsInterface {
+    static final String LOG_TAG = "RILB";
+
+    //***** Instance Variables
+    protected Context mContext;
+    protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
+    protected Object mStateMonitor = new Object();
+
+    protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
+    protected RegistrantList mOnRegistrants = new RegistrantList();
+    protected RegistrantList mAvailRegistrants = new RegistrantList();
+    protected RegistrantList mOffOrNotAvailRegistrants = new RegistrantList();
+    protected RegistrantList mNotAvailRegistrants = new RegistrantList();
+    protected RegistrantList mSIMReadyRegistrants = new RegistrantList();
+    protected RegistrantList mSIMLockedRegistrants = new RegistrantList();
+    protected RegistrantList mRUIMReadyRegistrants = new RegistrantList();
+    protected RegistrantList mRUIMLockedRegistrants = new RegistrantList();
+    protected RegistrantList mNVReadyRegistrants = new RegistrantList();
+    protected RegistrantList mCallStateRegistrants = new RegistrantList();
+    protected RegistrantList mNetworkStateRegistrants = new RegistrantList();
+    protected RegistrantList mDataConnectionRegistrants = new RegistrantList();
+    protected RegistrantList mRadioTechnologyChangedRegistrants = new RegistrantList();
+    protected RegistrantList mIccStatusChangedRegistrants = new RegistrantList();
+    protected RegistrantList mVoicePrivacyOnRegistrants = new RegistrantList();
+    protected RegistrantList mVoicePrivacyOffRegistrants = new RegistrantList();
+    protected Registrant mSMSRegistrant;
+    protected Registrant mNITZTimeRegistrant;
+    protected Registrant mSignalStrengthRegistrant;
+    protected Registrant mUSSDRegistrant;
+    protected Registrant mSmsOnSimRegistrant;
+    /** Registrant for handling SMS Status Reports */
+    protected Registrant mSmsStatusRegistrant;
+    /** Registrant for handling Supplementary Service Notifications */
+    protected Registrant mSsnRegistrant;
+    protected Registrant mStkSessionEndRegistrant;
+    protected Registrant mStkProCmdRegistrant;
+    protected Registrant mStkEventRegistrant;
+    protected Registrant mStkCallSetUpRegistrant;
+    /** Registrant for handling SIM/RUIM SMS storage full messages */
+    protected Registrant mIccSmsFullRegistrant;
+    /** Registrant for handling Icc Refresh notifications */
+    protected Registrant mIccRefreshRegistrant;
+    /** Registrant for handling RING notifications */
+    protected Registrant mRingRegistrant;
+    /** Registrant for handling RESTRICTED STATE changed notification */
+    protected Registrant mRestrictedStateRegistrant;
+
+    //Network Mode received from PhoneFactory
+    protected int mNetworkMode;
+    //CDMA subscription received from PhoneFactory
+    protected int mCdmaSubscription;
+    //Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
+    protected int mPhoneType;
+
+
+    public BaseCommands(Context context) {
+        mContext = context;  // May be null (if so we won't log statistics)
+    }
+
+    //***** CommandsInterface implementation
+
+    public RadioState getRadioState() {
+        return mState;
+    }
+
+
+    public void registerForRadioStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mRadioStateChangedRegistrants.add(r);
+            r.notifyRegistrant();
+        }
+    }
+
+    public void unregisterForRadioStateChanged(Handler h) {
+        synchronized (mStateMonitor) {
+            mRadioStateChangedRegistrants.remove(h);
+        }
+    }
+
+    public void registerForOn(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mOnRegistrants.add(r);
+
+            if (mState.isOn()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+    public void unregisterForOn(Handler h) {
+        synchronized (mStateMonitor) {
+            mOnRegistrants.remove(h);
+        }
+    }
+
+
+    public void registerForAvailable(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mAvailRegistrants.add(r);
+
+            if (mState.isAvailable()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForAvailable(Handler h) {
+        synchronized(mStateMonitor) {
+            mAvailRegistrants.remove(h);
+        }
+    }
+
+    public void registerForNotAvailable(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mNotAvailRegistrants.add(r);
+
+            if (!mState.isAvailable()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForNotAvailable(Handler h) {
+        synchronized (mStateMonitor) {
+            mNotAvailRegistrants.remove(h);
+        }
+    }
+
+    public void registerForOffOrNotAvailable(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mOffOrNotAvailRegistrants.add(r);
+
+            if (mState == RadioState.RADIO_OFF || !mState.isAvailable()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+    public void unregisterForOffOrNotAvailable(Handler h) {
+        synchronized(mStateMonitor) {
+            mOffOrNotAvailRegistrants.remove(h);
+        }
+    }
+
+
+    /** Any transition into SIM_READY */
+    public void registerForSIMReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mSIMReadyRegistrants.add(r);
+
+            if (mState.isSIMReady()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForSIMReady(Handler h) {
+        synchronized (mStateMonitor) {
+            mSIMReadyRegistrants.remove(h);
+        }
+    }
+
+    /** Any transition into RUIM_READY */
+    public void registerForRUIMReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mRUIMReadyRegistrants.add(r);
+
+            if (mState.isRUIMReady()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForRUIMReady(Handler h) {
+        synchronized(mStateMonitor) {
+            mRUIMReadyRegistrants.remove(h);
+        }
+    }
+
+    /** Any transition into NV_READY */
+    public void registerForNVReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mNVReadyRegistrants.add(r);
+
+            if (mState.isNVReady()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForNVReady(Handler h) {
+        synchronized (mStateMonitor) {
+            mNVReadyRegistrants.remove(h);
+        }
+    }
+
+    public void registerForSIMLockedOrAbsent(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mSIMLockedRegistrants.add(r);
+
+            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForSIMLockedOrAbsent(Handler h) {
+        synchronized (mStateMonitor) {
+            mSIMLockedRegistrants.remove(h);
+        }
+    }
+
+    public void registerForRUIMLockedOrAbsent(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mRUIMLockedRegistrants.add(r);
+
+            if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForRUIMLockedOrAbsent(Handler h) {
+        synchronized (mStateMonitor) {
+            mRUIMLockedRegistrants.remove(h);
+        }
+    }
+
+    public void registerForCallStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        mCallStateRegistrants.add(r);
+    }
+
+    public void unregisterForCallStateChanged(Handler h) {
+        mCallStateRegistrants.remove(h);
+    }
+
+    public void registerForNetworkStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        mNetworkStateRegistrants.add(r);
+    }
+
+    public void unregisterForNetworkStateChanged(Handler h) {
+        mNetworkStateRegistrants.remove(h);
+    }
+
+    public void registerForDataStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        mDataConnectionRegistrants.add(r);
+    }
+
+    public void unregisterForDataStateChanged(Handler h) {
+        mDataConnectionRegistrants.remove(h);
+    }
+
+    public void registerForRadioTechnologyChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mRadioTechnologyChangedRegistrants.add(r);
+    }
+
+    public void unregisterForRadioTechnologyChanged(Handler h) {
+        mRadioTechnologyChangedRegistrants.remove(h);
+    }
+
+    public void registerForIccStatusChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mIccStatusChangedRegistrants.add(r);
+    }
+
+    public void unregisterForIccStatusChanged(Handler h) {
+        mIccStatusChangedRegistrants.remove(h);
+    }
+
+    public void setOnNewSMS(Handler h, int what, Object obj) {
+        mSMSRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnNewSMS(Handler h) {
+        mSMSRegistrant.clear();
+    }
+
+    public void setOnSmsOnSim(Handler h, int what, Object obj) {
+        mSmsOnSimRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSmsOnSim(Handler h) {
+        mSmsOnSimRegistrant.clear();
+    }
+
+    public void setOnSmsStatus(Handler h, int what, Object obj) {
+        mSmsStatusRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSmsStatus(Handler h) {
+        mSmsStatusRegistrant.clear();
+    }
+
+    public void setOnSignalStrengthUpdate(Handler h, int what, Object obj) {
+        mSignalStrengthRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSignalStrengthUpdate(Handler h) {
+        mSignalStrengthRegistrant.clear();
+    }
+
+    public void setOnNITZTime(Handler h, int what, Object obj) {
+        mNITZTimeRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnNITZTime(Handler h) {
+        mNITZTimeRegistrant.clear();
+    }
+
+    public void setOnUSSD(Handler h, int what, Object obj) {
+        mUSSDRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnUSSD(Handler h) {
+        mUSSDRegistrant.clear();
+    }
+
+    public void setOnSuppServiceNotification(Handler h, int what, Object obj) {
+        mSsnRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSuppServiceNotification(Handler h) {
+        mSsnRegistrant.clear();
+    }
+
+    public void setOnStkSessionEnd(Handler h, int what, Object obj) {
+        mStkSessionEndRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkSessionEnd(Handler h) {
+        mStkSessionEndRegistrant.clear();
+    }
+
+    public void setOnStkProactiveCmd(Handler h, int what, Object obj) {
+        mStkProCmdRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkProactiveCmd(Handler h) {
+        mStkProCmdRegistrant.clear();
+    }
+
+    public void setOnStkEvent(Handler h, int what, Object obj) {
+        mStkEventRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkEvent(Handler h) {
+        mStkEventRegistrant.clear();
+    }
+
+    public void setOnStkCallSetUp(Handler h, int what, Object obj) {
+        mStkCallSetUpRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkCallSetUp(Handler h) {
+        mStkCallSetUpRegistrant.clear();
+    }
+
+    public void setOnIccSmsFull(Handler h, int what, Object obj) {
+        mIccSmsFullRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnIccSmsFull(Handler h) {
+        mIccSmsFullRegistrant.clear();
+    }
+
+    public void setOnIccRefresh(Handler h, int what, Object obj) {
+        mIccRefreshRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnIccRefresh(Handler h) {
+        mIccRefreshRegistrant.clear();
+    }
+
+    public void setOnCallRing(Handler h, int what, Object obj) {
+        mRingRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnCallRing(Handler h) {
+        mRingRegistrant.clear();
+    }
+
+    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mVoicePrivacyOnRegistrants.add(r);
+    }
+
+    public void unregisterForInCallVoicePrivacyOn(Handler h){
+        mVoicePrivacyOnRegistrants.remove(h);
+    }
+
+    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mVoicePrivacyOffRegistrants.add(r);
+    }
+
+    public void unregisterForInCallVoicePrivacyOff(Handler h){
+        mVoicePrivacyOffRegistrants.remove(h);
+    }
+
+    public void setOnRestrictedStateChanged(Handler h, int what, Object obj) {
+        mRestrictedStateRegistrant = new Registrant (h, what, obj);
+    }
+    
+    public void unSetOnRestrictedStateChanged(Handler h) {
+        mRestrictedStateRegistrant.clear();
+    }
+
+    //***** Protected Methods
+    /**
+     * Store new RadioState and send notification based on the changes
+     *
+     * This function is called only by RIL.java when receiving unsolicited
+     * RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
+     *
+     * RadioState has 5 values : RADIO_OFF, RADIO_UNAVAILABLE, SIM_NOT_READY,
+     * SIM_LOCKED_OR_ABSENT, and SIM_READY.
+     *
+     * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
+     */
+    protected void setRadioState(RadioState newState) {
+        RadioState oldState;
+
+        synchronized (mStateMonitor) {
+            if (Config.LOGV) {
+                Log.v(LOG_TAG, "setRadioState old: " + mState
+                    + " new " + newState);
+            }
+
+            oldState = mState;
+            mState = newState;
+
+            if (oldState == mState) {
+                // no state transition
+                return;
+            }
+
+            if (mContext != null &&
+                    newState == RadioState.RADIO_UNAVAILABLE &&
+                    oldState != RadioState.RADIO_OFF) {
+                Checkin.updateStats(mContext.getContentResolver(),
+                        Checkin.Stats.Tag.PHONE_RADIO_RESETS, 1, 0.0);
+            }
+
+            mRadioStateChangedRegistrants.notifyRegistrants();
+
+            if (mState.isAvailable() && !oldState.isAvailable()) {
+                Log.d(LOG_TAG,"Notifying: radio available");
+                mAvailRegistrants.notifyRegistrants();
+                onRadioAvailable();
+            }
+
+            if (!mState.isAvailable() && oldState.isAvailable()) {
+                Log.d(LOG_TAG,"Notifying: radio not available");
+                mNotAvailRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isSIMReady() && !oldState.isSIMReady()) {
+                Log.d(LOG_TAG,"Notifying: SIM ready");
+                mSIMReadyRegistrants.notifyRegistrants();
+            }
+
+            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
+                Log.d(LOG_TAG,"Notifying: SIM locked or absent");
+                mSIMLockedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isRUIMReady() && !oldState.isRUIMReady()) {
+                Log.d(LOG_TAG,"Notifying: RUIM ready");
+                mRUIMReadyRegistrants.notifyRegistrants();
+            }
+
+            if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
+                Log.d(LOG_TAG,"Notifying: RUIM locked or absent");
+                mRUIMLockedRegistrants.notifyRegistrants();
+            }
+            if (mState.isNVReady() && !oldState.isNVReady()) {
+                Log.d(LOG_TAG,"Notifying: NV ready");
+                mNVReadyRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isOn() && !oldState.isOn()) {
+                Log.d(LOG_TAG,"Notifying: Radio On");
+                mOnRegistrants.notifyRegistrants();
+            }
+
+            if ((!mState.isOn() || !mState.isAvailable())
+                && !((!oldState.isOn() || !oldState.isAvailable()))
+            ) {
+                Log.d(LOG_TAG,"Notifying: radio off or not available");
+                mOffOrNotAvailRegistrants.notifyRegistrants();
+            }
+
+            /* Radio Technology Change events
+             * NOTE: isGsm and isCdma have no common states in RADIO_OFF or RADIO_UNAVAILABLE; the
+             *   current phone is determined by mPhoneType
+             * NOTE: at startup no phone have been created and the RIL determines the mPhoneType
+             *   looking based on the networkMode set by the PhoneFactory in the constructor
+             */
+
+            if (mState.isGsm() && oldState.isCdma()) {
+                Log.d(LOG_TAG,"Notifying: radio technology change CDMA to GSM");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isGsm() && !oldState.isOn() && (mPhoneType == RILConstants.CDMA_PHONE)) {
+                Log.d(LOG_TAG,"Notifying: radio technology change CDMA OFF to GSM");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isCdma() && oldState.isGsm()) {
+                Log.d(LOG_TAG,"Notifying: radio technology change GSM to CDMA");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isCdma() && !oldState.isOn() && (mPhoneType == RILConstants.GSM_PHONE)) {
+                Log.d(LOG_TAG,"Notifying: radio technology change GSM OFF to CDMA");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+        }
+    }
+
+    protected void onRadioAvailable() {
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/Call.java b/telephony/java/com/android/internal/telephony/Call.java
index 82aeb25..70471b6 100644
--- a/telephony/java/com/android/internal/telephony/Call.java
+++ b/telephony/java/com/android/internal/telephony/Call.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony;
 
 import java.util.List;
+
 /**
  * {@hide}
  */
@@ -39,6 +40,13 @@
         }
     }
 
+
+    /* Instance Variables */
+
+    public State state = State.IDLE;
+
+
+
     /* Instance Methods */
 
     /** Do not modify the List result!!! This list is not yours to keep
@@ -46,36 +54,46 @@
      */
 
     public abstract List<Connection> getConnections();
-    public abstract State getState();
     public abstract Phone getPhone();
+    public abstract boolean isMultiparty();
+    public abstract void hangup() throws CallStateException;
+
 
     /**
      * hasConnection
-     * 
+     *
      * @param c a Connection object
      * @return true if the call contains the connection object passed in
      */
     public boolean hasConnection(Connection c) {
         return c.getCall() == this;
     }
-    
+
     /**
      * hasConnections
      * @return true if the call contains one or more connections
      */
     public boolean hasConnections() {
         List connections = getConnections();
-        
+
         if (connections == null) {
             return false;
         }
-        
+
         return connections.size() > 0;
     }
-    
+
+    /**
+     * getState
+     * @return state of class call
+     */
+    public State getState() {
+        return state;
+    }
+
     /**
      * isIdle
-     * 
+     *
      * FIXME rename
      * @return true if the call contains only disconnected connections (if any)
      */
@@ -93,27 +111,27 @@
         long time = Long.MAX_VALUE;
         Connection c;
         Connection earliest = null;
-        
+
         l = getConnections();
-        
+
         if (l.size() == 0) {
             return null;
         }
-        
+
         for (int i = 0, s = l.size() ; i < s ; i++) {
             c = (Connection) l.get(i);
             long t;
-            
+
             t = c.getCreateTime();
-            
+
             if (t < time) {
                 earliest = c;
             }
         }
-        
+
         return earliest;
     }
-    
+
     public long
     getEarliestCreateTime() {
         List l;
@@ -160,9 +178,6 @@
         return time;
     }
 
-    public abstract boolean isMultiparty();
-
-    public abstract void hangup() throws CallStateException;
 
     public boolean
     isDialingOrAlerting() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/CallForwardInfo.java b/telephony/java/com/android/internal/telephony/CallForwardInfo.java
similarity index 92%
rename from telephony/java/com/android/internal/telephony/gsm/CallForwardInfo.java
rename to telephony/java/com/android/internal/telephony/CallForwardInfo.java
index bf31b13..8b853b0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CallForwardInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallForwardInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.telephony.PhoneNumberUtils;
 
@@ -23,8 +23,7 @@
  *
  * {@hide}
  */
-public class CallForwardInfo
-{
+public class CallForwardInfo {
     public int             status;      /*1 = active, 0 = not active */
     public int             reason;      /* from TS 27.007 7.11 "reason" */
     public int             serviceClass; /* Sum of CommandsInterface.SERVICE_CLASS */
@@ -32,8 +31,7 @@
     public String          number;      /* "number" from TS 27.007 7.11 */
     public int             timeSeconds; /* for CF no reply only */
 
-    public String toString()
-    {
+    public String toString() {
         return super.toString() + (status == 0 ? " not active " : " active ")
             + " reason: " + reason
             + " serviceClass: " + serviceClass
diff --git a/telephony/java/com/android/internal/telephony/CallTracker.java b/telephony/java/com/android/internal/telephony/CallTracker.java
new file mode 100644
index 0000000..eb339f8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CallTracker.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.CommandException;
+
+
+/**
+ * {@hide}
+ */
+public abstract class CallTracker extends Handler {
+
+    private static final boolean DBG_POLL = false;
+
+    //***** Constants
+
+    static final int POLL_DELAY_MSEC = 250;
+
+    protected int pendingOperations;
+    protected boolean needsPoll;
+    protected Message lastRelevantPoll;
+
+    public CommandsInterface cm;
+
+
+    //***** Events
+
+    protected static final int EVENT_POLL_CALLS_RESULT    = 1;
+    protected static final int EVENT_CALL_STATE_CHANGE    = 2;
+    protected static final int EVENT_REPOLL_AFTER_DELAY   = 3;
+    protected static final int EVENT_OPERATION_COMPLETE       = 4;
+    protected static final int EVENT_GET_LAST_CALL_FAIL_CAUSE = 5;
+
+    protected static final int EVENT_SWITCH_RESULT        = 8;
+    protected static final int EVENT_RADIO_AVAILABLE      = 9;
+    protected static final int EVENT_RADIO_NOT_AVAILABLE  = 10;
+    protected static final int EVENT_CONFERENCE_RESULT    = 11;
+    protected static final int EVENT_SEPARATE_RESULT      = 12;
+    protected static final int EVENT_ECT_RESULT           = 13;
+
+
+    protected void pollCallsWhenSafe() {
+        needsPoll = true;
+
+        if (checkNoOperationsPending()) {
+            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
+            cm.getCurrentCalls(lastRelevantPoll);
+        }
+    }
+
+    protected void
+    pollCallsAfterDelay() {
+        Message msg = obtainMessage();
+
+        msg.what = EVENT_REPOLL_AFTER_DELAY;
+        sendMessageDelayed(msg, POLL_DELAY_MSEC);
+    }
+
+    protected boolean
+    isCommandExceptionRadioNotAvailable(Throwable e) {
+        return e != null && e instanceof CommandException
+                && ((CommandException)e).getCommandError()
+                        == CommandException.Error.RADIO_NOT_AVAILABLE;
+    }
+
+    protected abstract void handlePollCalls(AsyncResult ar);
+
+    protected void handleRadioAvailable() {
+        pollCallsWhenSafe();
+    }
+
+    /**
+     * Obtain a complete message that indicates that this operation
+     * does not require polling of getCurrentCalls(). However, if other
+     * operations that do need getCurrentCalls() are pending or are
+     * scheduled while this operation is pending, the invocation
+     * of getCurrentCalls() will be postponed until this
+     * operation is also complete.
+     */
+    protected Message
+    obtainNoPollCompleteMessage(int what) {
+        pendingOperations++;
+        lastRelevantPoll = null;
+        return obtainMessage(what);
+    }
+
+    /**
+     * @return true if we're idle or there's a call to getCurrentCalls() pending
+     * but nothing else
+     */
+    private boolean
+    checkNoOperationsPending() {
+        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
+                pendingOperations);
+        return pendingOperations == 0;
+    }
+
+
+    //***** Overridden from Handler
+    public abstract void handleMessage (Message msg);
+
+    protected abstract void log(String msg);
+
+}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 145e5d8..04da9f7 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -37,7 +37,7 @@
 public class CallerInfoAsyncQuery {
     
     private static final boolean DBG = false;
-    private static final String LOG_TAG = "CallerInfoAsyncQuery";
+    private static final String LOG_TAG = "PHONE";
     
     private static final int EVENT_NEW_QUERY = 1;
     private static final int EVENT_ADD_LISTENER = 2;
diff --git a/telephony/java/com/android/internal/telephony/gsm/CommandException.java b/telephony/java/com/android/internal/telephony/CommandException.java
similarity index 77%
rename from telephony/java/com/android/internal/telephony/gsm/CommandException.java
rename to telephony/java/com/android/internal/telephony/CommandException.java
index 5cf48f3..a5d11cf 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CommandException.java
+++ b/telephony/java/com/android/internal/telephony/CommandException.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.RILConstants;
 
 import android.util.Log;
 
 /**
  * {@hide}
  */
-public class CommandException extends RuntimeException
-{
+public class CommandException extends RuntimeException {
     private Error e;
 
     public enum Error {
@@ -38,30 +39,28 @@
         SMS_FAIL_RETRY,
     }
 
-    public CommandException(Error e)
-    {
+    public CommandException(Error e) {
         super(e.toString());
         this.e = e;
     }
 
     public static CommandException
-    fromRilErrno(int ril_errno)
-    {
+    fromRilErrno(int ril_errno) {
         switch(ril_errno) {
             case RILConstants.SUCCESS:                       return null;
-            case RILConstants.RIL_ERRNO_INVALID_RESPONSE:    
+            case RILConstants.RIL_ERRNO_INVALID_RESPONSE:
                 return new CommandException(Error.INVALID_RESPONSE);
-            case RILConstants.RADIO_NOT_AVAILABLE:           
+            case RILConstants.RADIO_NOT_AVAILABLE:
                 return new CommandException(Error.RADIO_NOT_AVAILABLE);
-            case RILConstants.GENERIC_FAILURE:               
+            case RILConstants.GENERIC_FAILURE:
                 return new CommandException(Error.GENERIC_FAILURE);
-            case RILConstants.PASSWORD_INCORRECT:            
+            case RILConstants.PASSWORD_INCORRECT:
                 return new CommandException(Error.PASSWORD_INCORRECT);
-            case RILConstants.SIM_PIN2:                      
+            case RILConstants.SIM_PIN2:
                 return new CommandException(Error.SIM_PIN2);
-            case RILConstants.SIM_PUK2:                      
+            case RILConstants.SIM_PUK2:
                 return new CommandException(Error.SIM_PUK2);
-            case RILConstants.REQUEST_NOT_SUPPORTED:         
+            case RILConstants.REQUEST_NOT_SUPPORTED:
                 return new CommandException(Error.REQUEST_NOT_SUPPORTED);
             case RILConstants.OP_NOT_ALLOWED_DURING_VOICE_CALL:
                 return new CommandException(Error.OP_NOT_ALLOWED_DURING_VOICE_CALL);
@@ -75,8 +74,7 @@
         }
     }
 
-    public Error getCommandError()
-    {
+    public Error getCommandError() {
         return e;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
similarity index 68%
rename from telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java
rename to telephony/java/com/android/internal/telephony/CommandsInterface.java
index 7915798..aec7238 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -14,50 +14,79 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+package com.android.internal.telephony;
+
 import android.os.Message;
 import android.os.Handler;
 
+
 /**
  * {@hide}
  */
-public interface CommandsInterface
-{
+public interface CommandsInterface {
     enum RadioState {
         RADIO_OFF,         /* Radio explictly powered off (eg CFUN=0) */
         RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */
         SIM_NOT_READY,     /* Radio is on, but the SIM interface is not ready */
-        SIM_LOCKED_OR_ABSENT,  /* SIM PIN locked, PUK required, network 
+        SIM_LOCKED_OR_ABSENT,  /* SIM PIN locked, PUK required, network
                                personalization, or SIM absent */
-        SIM_READY;         /* Radio is on and SIM interface is available */
+        SIM_READY,         /* Radio is on and SIM interface is available */
+        RUIM_NOT_READY,    /* Radio is on, but the RUIM interface is not ready */
+        RUIM_READY,        /* Radio is on and the RUIM interface is available */
+        RUIM_LOCKED_OR_ABSENT, /* RUIM PIN locked, PUK required, network
+                                  personalization locked, or RUIM absent */
+        NV_NOT_READY,      /* Radio is on, but the NV interface is not available */
+        NV_READY;          /* Radio is on and the NV interface is available */
 
-        boolean isOn() /* and available...*/
-        {
+        public boolean isOn() /* and available...*/ {
+            return this == SIM_NOT_READY
+                    || this == SIM_LOCKED_OR_ABSENT
+                    || this == SIM_READY
+                    || this == RUIM_NOT_READY
+                    || this == RUIM_READY
+                    || this == RUIM_LOCKED_OR_ABSENT
+                    || this == NV_NOT_READY
+                    || this == NV_READY;
+        }
+
+        public boolean isAvailable() {
+            return this != RADIO_UNAVAILABLE;
+        }
+
+        public boolean isSIMReady() {
+            return this == SIM_READY;
+        }
+
+        public boolean isRUIMReady() {
+            return this == RUIM_READY;
+        }
+
+        public boolean isNVReady() {
+            return this == NV_READY;
+        }
+
+        public boolean isGsm() {
             return this == SIM_NOT_READY
                     || this == SIM_LOCKED_OR_ABSENT
                     || this == SIM_READY;
         }
 
-        boolean isAvailable()
-        {
-            return this != RADIO_UNAVAILABLE;
-        }
-
-        boolean isSIMReady()
-        {
-            // if you add new states after SIM_READY, include them too
-            return this == SIM_READY;
+        public boolean isCdma() {
+            return this ==  RUIM_NOT_READY
+                    || this == RUIM_READY
+                    || this == RUIM_LOCKED_OR_ABSENT
+                    || this == NV_NOT_READY
+                    || this == NV_READY;
         }
     }
 
-    enum SimStatus {
-        SIM_ABSENT,
-        SIM_NOT_READY,
-        SIM_READY,
-        SIM_PIN,
-        SIM_PUK,
-        SIM_NETWORK_PERSONALIZATION
+    enum IccStatus {
+        ICC_ABSENT,
+        ICC_NOT_READY,
+        ICC_READY,
+        ICC_PIN,
+        ICC_PUK,
+        ICC_NETWORK_PERSONALIZATION
     }
 
     //***** Constants
@@ -93,7 +122,7 @@
     static final String CB_FACILITY_BA_MT        = "AC";
     static final String CB_FACILITY_BA_SIM       = "SC";
     static final String CB_FACILITY_BA_FD        = "FD";
-                  
+
 
     // Used for various supp services apis
     // See 27.007 +CCFC or +CLCK
@@ -102,7 +131,7 @@
     static final int SERVICE_CLASS_DATA     = (1 << 1); //synoym for 16+32+64+128
     static final int SERVICE_CLASS_FAX      = (1 << 2);
     static final int SERVICE_CLASS_SMS      = (1 << 3);
-    static final int SERVICE_CLASS_DATA_SYNC = (1 << 4); 
+    static final int SERVICE_CLASS_DATA_SYNC = (1 << 4);
     static final int SERVICE_CLASS_DATA_ASYNC = (1 << 5);
     static final int SERVICE_CLASS_PACKET   = (1 << 6);
     static final int SERVICE_CLASS_PAD      = (1 << 7);
@@ -122,8 +151,8 @@
 
     RadioState getRadioState();
 
-    /** 
-     * Fires on any RadioState transition 
+    /**
+     * Fires on any RadioState transition
      * Always fires immediately as well
      *
      * do not attempt to calculate transitions by storing getRadioState() values
@@ -131,58 +160,85 @@
      * registration methods
      */
     void registerForRadioStateChanged(Handler h, int what, Object obj);
+    void unregisterForRadioStateChanged(Handler h);
 
-    /** 
-     * Fires on any transition into RadioState.isOn() 
+    /**
+     * Fires on any transition into RadioState.isOn()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForOn(Handler h, int what, Object obj);
+    void unregisterForOn(Handler h);
 
-    /** 
-     * Fires on any transition out of RadioState.isAvailable() 
+    /**
+     * Fires on any transition out of RadioState.isAvailable()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForAvailable(Handler h, int what, Object obj);
-    //void unregisterForAvailable(Handler h);
-    /** 
+    void unregisterForAvailable(Handler h);
+
+    /**
      * Fires on any transition into !RadioState.isAvailable()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForNotAvailable(Handler h, int what, Object obj);
-    //void unregisterForNotAvailable(Handler h);
-    /** 
+    void unregisterForNotAvailable(Handler h);
+
+    /**
      * Fires on any transition into RADIO_OFF or !RadioState.isAvailable()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForOffOrNotAvailable(Handler h, int what, Object obj);
-    //void unregisterForNotAvailable(Handler h);
+    void unregisterForOffOrNotAvailable(Handler h);
 
-    /** 
+    /**
      * Fires on any transition into SIM_READY
      * Fires immediately if if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForSIMReady(Handler h, int what, Object obj);
-    //void unregisterForSIMReady(Handler h);
+    void unregisterForSIMReady(Handler h);
+
     /** Any transition into SIM_LOCKED_OR_ABSENT */
     void registerForSIMLockedOrAbsent(Handler h, int what, Object obj);
-    //void unregisterForSIMLockedOrAbsent(Handler h);
+    void unregisterForSIMLockedOrAbsent(Handler h);
 
     void registerForCallStateChanged(Handler h, int what, Object obj);
-    //void unregisterForCallStateChanged(Handler h);
+    void unregisterForCallStateChanged(Handler h);
     void registerForNetworkStateChanged(Handler h, int what, Object obj);
-    //void unregisterForNetworkStateChanged(Handler h);
-    void registerForPDPStateChanged(Handler h, int what, Object obj);
-    //void unregisterForPDPStateChanged(Handler h);
+    void unregisterForNetworkStateChanged(Handler h);
+    void registerForDataStateChanged(Handler h, int what, Object obj);
+    void unregisterForDataStateChanged(Handler h);
+
+    void registerForRadioTechnologyChanged(Handler h, int what, Object obj);
+    void unregisterForRadioTechnologyChanged(Handler h);
+    void registerForNVReady(Handler h, int what, Object obj);
+    void unregisterForNVReady(Handler h);
+    void registerForRUIMLockedOrAbsent(Handler h, int what, Object obj);
+    void unregisterForRUIMLockedOrAbsent(Handler h);
+
+    /** InCall voice privacy notifications */
+    void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj);
+    void unregisterForInCallVoicePrivacyOn(Handler h);
+    void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj);
+    void unregisterForInCallVoicePrivacyOff(Handler h);
+
+    /**
+     * Fires on any transition into RUIM_READY
+     * Fires immediately if if currently in that state
+     * In general, actions should be idempotent. State may change
+     * before event is received.
+     */
+    void registerForRUIMReady(Handler h, int what, Object obj);
+    void unregisterForRUIMReady(Handler h);
 
     /**
      * unlike the register* methods, there's only one new SMS handler
@@ -192,21 +248,24 @@
      * AsyncResult.result is a String containing the SMS PDU
      */
     void setOnNewSMS(Handler h, int what, Object obj);
+    void unSetOnNewSMS(Handler h);
 
    /**
-     * Register for NEW_SMS_ON_SIM unsolicited message 
+     * Register for NEW_SMS_ON_SIM unsolicited message
      *
      * AsyncResult.result is an int array containing the index of new SMS
      */
     void setOnSmsOnSim(Handler h, int what, Object obj);
+    void unSetOnSmsOnSim(Handler h);
 
     /**
-     * Register for NEW_SMS_STATUS_REPORT unsolicited message 
+     * Register for NEW_SMS_STATUS_REPORT unsolicited message
      *
      * AsyncResult.result is a String containing the status report PDU
      */
     void setOnSmsStatus(Handler h, int what, Object obj);
-    
+    void unSetOnSmsStatus(Handler h);
+
     /**
      * unlike the register* methods, there's only one NITZ time handler
      *
@@ -220,13 +279,14 @@
      * seconds on system startup
      */
     void setOnNITZTime(Handler h, int what, Object obj);
+    void unSetOnNITZTime(Handler h);
 
     /**
      * unlike the register* methods, there's only one USSD notify handler
      *
      * Represents the arrival of a USSD "notify" message, which may
      * or may not have been triggered by a previous USSD send
-     * 
+     *
      * AsyncResult.result is a String[]
      * ((String[])(AsyncResult.result))[0] contains status code
      *      "0"   USSD-Notify -- text in ((const char **)data)[1]
@@ -241,26 +301,29 @@
      */
 
     void setOnUSSD(Handler h, int what, Object obj);
+    void unSetOnUSSD(Handler h);
 
     /**
      * unlike the register* methods, there's only one signal strength handler
-     * AsyncResult.result is an int[2]     
-     * response.obj.result[0] is received signal strength (0-31, 99) 
-     * response.obj.result[1] is  bit error rate (0-7, 99) 
+     * AsyncResult.result is an int[2]
+     * response.obj.result[0] is received signal strength (0-31, 99)
+     * response.obj.result[1] is  bit error rate (0-7, 99)
      * as defined in TS 27.007 8.5
      */
 
     void setOnSignalStrengthUpdate(Handler h, int what, Object obj);
+    void unSetOnSignalStrengthUpdate(Handler h);
 
     /**
-     * Sets the handler for SIM SMS storage full unsolicited message.
+     * Sets the handler for SIM/RUIM SMS storage full unsolicited message.
      * Unlike the register* methods, there's only one notification handler
      *
      * @param h Handler for notification message.
      * @param what User-defined message code.
      * @param obj User object.
      */
-    void setOnSimSmsFull(Handler h, int what, Object obj);
+    void setOnIccSmsFull(Handler h, int what, Object obj);
+    void unSetOnIccSmsFull(Handler h);
 
     /**
      * Sets the handler for SIM Refresh notifications.
@@ -270,8 +333,9 @@
      * @param what User-defined message code.
      * @param obj User object.
      */
-    void setOnSimRefresh(Handler h, int what, Object obj);
-    
+    void setOnIccRefresh(Handler h, int what, Object obj);
+    void unSetOnIccRefresh(Handler h);
+
     /**
      * Sets the handler for RING notifications.
      * Unlike the register* methods, there's only one notification handler
@@ -281,7 +345,8 @@
      * @param obj User object.
      */
     void setOnCallRing(Handler h, int what, Object obj);
-    
+    void unSetOnCallRing(Handler h);
+
     /**
      * Sets the handler for RESTRICTED_STATE changed notification, 
      * eg, for Domain Specific Access Control
@@ -292,7 +357,8 @@
      */
 
     void setOnRestrictedStateChanged(Handler h, int what, Object obj);
-    
+    void unSetOnRestrictedStateChanged(Handler h);
+
     /**
      * Sets the handler for Supplementary Service Notifications.
      * Unlike the register* methods, there's only one notification handler
@@ -302,6 +368,7 @@
      * @param obj User object.
      */
     void setOnSuppServiceNotification(Handler h, int what, Object obj);
+    void unSetOnSuppServiceNotification(Handler h);
 
     /**
      * Sets the handler for Session End Notifications for STK.
@@ -312,6 +379,7 @@
      * @param obj User object.
      */
     void setOnStkSessionEnd(Handler h, int what, Object obj);
+    void unSetOnStkSessionEnd(Handler h);
 
     /**
      * Sets the handler for Proactive Commands for STK.
@@ -322,6 +390,7 @@
      * @param obj User object.
      */
     void setOnStkProactiveCmd(Handler h, int what, Object obj);
+    void unSetOnStkProactiveCmd(Handler h);
 
     /**
      * Sets the handler for Event Notifications for STK.
@@ -332,6 +401,7 @@
      * @param obj User object.
      */
     void setOnStkEvent(Handler h, int what, Object obj);
+    void unSetOnStkEvent(Handler h);
 
     /**
      * Sets the handler for Call Set Up Notifications for STK.
@@ -342,6 +412,7 @@
      * @param obj User object.
      */
     void setOnStkCallSetUp(Handler h, int what, Object obj);
+    void unSetOnStkCallSetUp(Handler h);
 
     /**
      * Enables/disbables supplementary service related notifications from
@@ -351,19 +422,21 @@
      * @param result Message to be posted when command completes.
      */
     void setSuppServiceNotifications(boolean enable, Message result);
+    //void unSetSuppServiceNotifications(Handler h);
+
 
     /**
-     * Returns current SIM status.
+     * Returns current ICC status.
      *
-     * AsyncResult.result is SimStatus
-     * 
+     * AsyncResult.result is IccStatus
+     *
      */
 
-    void getSimStatus(Message result);    
+    void getIccStatus(Message result);
 
     /**
-     * Supply the SIM PIN to the SIM card
-     * 
+     * Supply the ICC PIN to the ICC card
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -373,11 +446,11 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPin(String pin, Message result);
+    void supplyIccPin(String pin, Message result);
 
     /**
-     * Supply the SIM PUK to the SIM card
-     * 
+     * Supply the ICC PUK to the ICC card
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -387,13 +460,13 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPuk(String puk, String newPin, Message result);
+    void supplyIccPuk(String puk, String newPin, Message result);
 
     /**
-     * Supply the SIM PIN2 to the SIM card
-     * Only called following operation where SIM_PIN2 was
+     * Supply the ICC PIN2 to the ICC card
+     * Only called following operation where ICC_PIN2 was
      * returned as a a failure from a previous operation
-     * 
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -403,13 +476,13 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPin2(String pin2, Message result);
+    void supplyIccPin2(String pin2, Message result);
 
     /**
      * Supply the SIM PUK2 to the SIM card
      * Only called following operation where SIM_PUK2 was
      * returned as a a failure from a previous operation
-     * 
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -419,16 +492,16 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPuk2(String puk2, String newPin2, Message result);
+    void supplyIccPuk2(String puk2, String newPin2, Message result);
 
-    void changeSimPin(String oldPin, String newPin, Message result);
-    void changeSimPin2(String oldPin2, String newPin2, Message result);
+    void changeIccPin(String oldPin, String newPin, Message result);
+    void changeIccPin2(String oldPin2, String newPin2, Message result);
 
     void changeBarringPassword(String facility, String oldPwd, String newPwd, Message result);
 
     void supplyNetworkDepersonalization(String netpin, Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -438,16 +511,26 @@
      */
     void getCurrentCalls (Message result);
 
-    /** 
+    /**
+     *  returned message
+     *  retMsg.obj = AsyncResult ar
+     *  ar.exception carries exception on failure
+     *  ar.userObject contains the orignal value of result.obj
+     *  ar.result contains a List of PDPContextState
+     *  @deprecated
+     */
+    void getPDPContextList(Message result);
+
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result contains a List of PDPContextState
      */
-    void getPDPContextList(Message result);
+    void getDataCallList(Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -460,7 +543,7 @@
      */
     void dial (String address, int clirMode, Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -469,7 +552,7 @@
      */
     void getIMSI(Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -478,7 +561,7 @@
      */
     void getIMEI(Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -487,7 +570,7 @@
      */
     void getIMEISV(Message result);
 
-    /** 
+    /**
      * Hang up one individual connection.
      *  returned message
      *  retMsg.obj = AsyncResult ar
@@ -512,7 +595,7 @@
 
     /**
      * 3GPP 22.030 6.5.5
-     * "Releases all active calls (if any exist) and accepts 
+     * "Releases all active calls (if any exist) and accepts
      *  the other (held or waiting) call."
      *
      *  ar.exception carries exception on failure
@@ -523,7 +606,7 @@
 
     /**
      * 3GPP 22.030 6.5.5
-     * "Places all active calls (if any exist) on hold and accepts 
+     * "Places all active calls (if any exist) on hold and accepts
      *  the other (held or waiting) call."
      *
      *  ar.exception carries exception on failure
@@ -539,12 +622,27 @@
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void conference (Message result);
 
     /**
+     * Set preferred Voice Privacy (VP).
+     *
+     * @param enable true is enhanced and false is normal VP
+     * @param result is a callback message
+     */
+    void setPreferredVoicePrivacy(boolean enable, Message result);
+
+    /**
+     * Get currently set preferred Voice Privacy (VP) mode.
+     *
+     * @param result is a callback message
+     */
+    void getPreferredVoicePrivacy(Message result);
+
+    /**
      * 3GPP 22.030 6.5.5
-     * "Places all active calls on hold except call X with which 
+     * "Places all active calls on hold except call X with which
      *  communication shall be supported."
      */
     void separateConnection (int gsmIndex, Message result);
@@ -554,15 +652,15 @@
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void acceptCall (Message result);
 
-    /** 
+    /**
      *  also known as UDUB
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void rejectCall (Message result);
 
     /**
@@ -586,14 +684,21 @@
     void getLastCallFailCause (Message result);
 
 
-    /** 
+    /**
      * Reason for last PDP context deactivate or failure to activate
      * cause code returned as int[0] in Message.obj.response
      * returns an integer cause code defined in TS 24.008
      * section 6.1.3.1.3 or close approximation
+     * @deprecated
      */
     void getLastPdpFailCause (Message result);
 
+    /**
+     * The preferred new alternative to getLastPdpFailCause
+     * that is also CDMA-compatible.
+     */
+    void getLastDataCallFailCause (Message result);
+
     void setMute (boolean enableMute, Message response);
 
     void getMute (Message response);
@@ -601,8 +706,8 @@
     /**
      * response.obj is an AsyncResult
      * response.obj.result is an int[2]
-     * response.obj.result[0] is received signal strength (0-31, 99) 
-     * response.obj.result[1] is  bit error rate (0-7, 99) 
+     * response.obj.result[0] is received signal strength (0-31, 99)
+     * response.obj.result[1] is  bit error rate (0-7, 99)
      * as defined in TS 27.007 8.5
      */
     void getSignalStrength (Message response);
@@ -612,21 +717,21 @@
      * response.obj.result is an int[3]
      * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2
      * response.obj.result[1] is LAC if registered or -1 if not
-     * response.obj.result[2] is CID if registered or -1 if not 
+     * response.obj.result[2] is CID if registered or -1 if not
      * valid LAC and CIDs are 0x0000 - 0xffff
-     * 
+     *
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" above
      */
     void getRegistrationState (Message response);
-                                                                                                            
+
     /**
      * response.obj.result is an int[3]
      * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2
      * response.obj.result[1] is LAC if registered or -1 if not
-     * response.obj.result[2] is CID if registered or -1 if not 
+     * response.obj.result[2] is CID if registered or -1 if not
      * valid LAC and CIDs are 0x0000 - 0xffff
-     * 
+     *
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" above
      */
@@ -637,14 +742,14 @@
      * response.obj.result[0] is long alpha or null if unregistered
      * response.obj.result[1] is short alpha or null if unregistered
      * response.obj.result[2] is numeric or null if unregistered
-     */ 
+     */
     void getOperator(Message response);
 
     /**
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void sendDtmf(char c, Message result);
 
 
@@ -667,26 +772,40 @@
      * smscPDU is smsc address in PDU form GSM BCD format prefixed
      *      by a length byte (as expected by TS 27.005) or NULL for default SMSC
      * pdu is SMS in PDU format as an ASCII hex string
-     *      less the SMSC address     
+     *      less the SMSC address
      */
     void sendSMS (String smscPDU, String pdu, Message response);
 
     /**
+     * @param pdu is CDMA-SMS in internal pseudo-PDU format
+     * @param response sent when operation completes
+     */
+    void sendCdmaSms(byte[] pdu, Message response);
+
+    /**
      * Deletes the specified SMS record from SIM memory (EF_SMS).
-     * 
+     *
      * @param index index of the SMS record to delete
      * @param response sent when operation completes
      */
     void deleteSmsOnSim(int index, Message response);
 
     /**
+     * Deletes the specified SMS record from RUIM memory (EF_SMS in DF_CDMA).
+     *
+     * @param index index of the SMS record to delete
+     * @param response sent when operation completes
+     */
+    void deleteSmsOnRuim(int index, Message response);
+
+    /**
      * Writes an SMS message to SIM memory (EF_SMS).
-     * 
+     *
      * @param status status of message on SIM.  One of:
-     *                  SmsManger.STATUS_ON_SIM_READ
-     *                  SmsManger.STATUS_ON_SIM_UNREAD
-     *                  SmsManger.STATUS_ON_SIM_SENT
-     *                  SmsManger.STATUS_ON_SIM_UNSENT
+     *                  SmsManger.STATUS_ON_ICC_READ
+     *                  SmsManger.STATUS_ON_ICC_UNREAD
+     *                  SmsManger.STATUS_ON_ICC_SENT
+     *                  SmsManger.STATUS_ON_ICC_UNSENT
      * @param pdu message PDU, as hex string
      * @param response sent when operation completes.
      *                  response.obj will be an AsyncResult, and will indicate
@@ -694,89 +813,105 @@
      */
     void writeSmsToSim(int status, String smsc, String pdu, Message response);
 
+    void writeSmsToRuim(int status, String pdu, Message response);
+
+    /**
+     * @deprecated
+     * @param apn
+     * @param user
+     * @param password
+     * @param response
+     */
     void setupDefaultPDP(String apn, String user, String password, Message response);
 
+    /**
+     * @deprecated
+     * @param cid
+     * @param response
+     */
     void deactivateDefaultPDP(int cid, Message response);
 
     void setRadioPower(boolean on, Message response);
 
     void acknowledgeLastIncomingSMS(boolean success, Message response);
 
-    /** 
-     * parameters equivilient to 27.007 AT+CRSM command 
+    void acknowledgeLastIncomingCdmaSms(boolean success, Message response);
+
+    /**
+     * parameters equivilient to 27.007 AT+CRSM command
      * response.obj will be an AsyncResult
-     * response.obj.userObj will be a SimIoResult on success
+     * response.obj.userObj will be a IccIoResult on success
      */
-    void simIO (int command, int fileid, String path, int p1, int p2, int p3, 
+    void iccIO (int command, int fileid, String path, int p1, int p2, int p3,
             String data, String pin2, Message response);
 
     /**
      * (AsyncResult)response.obj).result is an int[] with element [0] set to
-     * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned". 
+     * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned".
      *
      * @param response is callback message
      */
-    
+
     void queryCLIP(Message response);
 
     /**
      * response.obj will be a an int[2]
      *
      * response.obj[0] will be TS 27.007 +CLIR parameter 'n'
-     *  0 presentation indicator is used according to the subscription of the CLIR service 
-     *  1 CLIR invocation 
-     *  2 CLIR suppression 
+     *  0 presentation indicator is used according to the subscription of the CLIR service
+     *  1 CLIR invocation
+     *  2 CLIR suppression
      *
      * response.obj[1] will be TS 27.007 +CLIR parameter 'm'
-     *  0 CLIR not provisioned 
-     *  1 CLIR provisioned in permanent mode 
-     *  2 unknown (e.g. no network, etc.) 
-     *  3 CLIR temporary mode presentation restricted 
-     *  4 CLIR temporary mode presentation allowed 
+     *  0 CLIR not provisioned
+     *  1 CLIR provisioned in permanent mode
+     *  2 unknown (e.g. no network, etc.)
+     *  3 CLIR temporary mode presentation restricted
+     *  4 CLIR temporary mode presentation allowed
      */
 
     void getCLIR(Message response);
-    
+
     /**
      * clirMode is one of the CLIR_* constants above
      *
      * response.obj is null
      */
-    
+
     void setCLIR(int clirMode, Message response);
 
     /**
      * (AsyncResult)response.obj).result is an int[] with element [0] set to
-     * 0 for disabled, 1 for enabled. 
+     * 0 for disabled, 1 for enabled.
      *
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    
+
     void queryCallWaiting(int serviceClass, Message response);
-    
+
     /**
      * @param enable is true to enable, false to disable
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    
+
     void setCallWaiting(boolean enable, int serviceClass, Message response);
 
     /**
      * @param action is one of CF_ACTION_*
      * @param cfReason is one of CF_REASON_*
-     * @param serviceClass is a sum of SERVICE_CLASSS_* 
+     * @param serviceClass is a sum of SERVICE_CLASSS_*
      */
-    void setCallForward(int action, int cfReason, int serviceClass, 
-                String number, int timeSeconds, Message response); 
+    void setCallForward(int action, int cfReason, int serviceClass,
+                String number, int timeSeconds, Message response);
 
     /**
      * cfReason is one of CF_REASON_*
      *
      * ((AsyncResult)response.obj).result will be an array of
      * CallForwardInfo's
-     * 
+     *
      * An array of length 0 means "disabled for all codes"
      */
     void queryCallForwardStatus(int cfReason, int serviceClass,
@@ -815,7 +950,7 @@
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    
+
     void queryFacilityLock (String facility, String password, int serviceClass,
         Message response);
 
@@ -828,7 +963,7 @@
      */
     void setFacilityLock (String facility, boolean lockState, String password,
         int serviceClass, Message response);
-    
+
 
     void sendUSSD (String ussdString, Message response);
 
@@ -850,7 +985,7 @@
 
     /**
      * Query the list of band mode supported by RF.
-     * 
+     *
      * @param response is callback message
      *        ((AsyncResult)response.obj).result  is an int[] with every
      *        element representing one avialable BM_*_BAND
@@ -923,4 +1058,136 @@
      * @param response Callback message
      */
     public void handleCallSetupRequestFromSim(boolean accept, Message response);
+
+    //***** new Methods for CDMA support
+
+    /**
+     * Request the device ESN / MEID / IMEI / IMEISV.
+     * "response" is const char **
+     *   [0] is IMEI if GSM subscription is available
+     *   [1] is IMEISV if GSM subscription is available
+     *   [2] is ESN if CDMA subscription is available
+     *   [3] is MEID if CDMA subscription is available
+     */
+    public void getDeviceIdentity(Message response);
+
+    /**
+     * Request the device IMSI_M / MDN / AH_SID / H_SID / H_NID.
+     * "response" is const char **
+     *   [0] is IMSI_M if CDMA subscription is available
+     *   [1] is MDN if CDMA subscription is available
+     *   [2] is AH_SID (Analog Home SID) if CDMA subscription
+     *   [3] is H_SID (Home SID) if CDMA subscription is available
+     *   [4] is H_NID (Home SID) if CDMA subscription is available
+     */
+    public void getCDMASubscription(Message response);
+
+    /**
+     * Send Flash Code.
+     * "response" is is NULL
+     *   [0] is a FLASH string
+     */
+    public void sendCDMAFeatureCode(String FeatureCode, Message response);
+
+    /** Set the Phone type created */
+    void setPhoneType(int phoneType);
+    /**
+     *  Query the CDMA roaming preference setting
+     *
+     * @param response is callback message to report one of  CDMA_RM_*
+     */
+    void queryCdmaRoamingPreference(Message response);
+
+    /**
+     *  Requests to set the CDMA roaming preference
+     * @param cdmaRoamingType one of  CDMA_RM_*
+     * @param response is callback message
+     */
+    void setCdmaRoamingPreference(int cdmaRoamingType, Message response);
+
+    /**
+     *  Requests to set the CDMA subscription mode
+     * @param cdmaSubscriptionType one of  CDMA_SUBSCRIPTION_*
+     * @param response is callback message
+     */
+    void setCdmaSubscription(int cdmaSubscriptionType, Message response);
+
+    /**
+     *  Set the TTY mode for the CDMA phone
+     *
+     * @param enable is true to enable, false to disable
+     * @param response is callback message
+     */
+    void setTTYModeEnabled(boolean enable, Message response);
+
+    /**
+     *  Query the TTY mode for the CDMA phone
+     * (AsyncResult)response.obj).result is an int[] with element [0] set to
+     * 0 for disabled, 1 for enabled.
+     *
+     * @param response is callback message
+     */
+    void queryTTYModeEnabled(Message response);
+
+    /**
+     * Setup a packet data connection On successful completion, the result
+     * message will return the following: [0] indicating PDP CID, which is
+     * generated by RIL. This Connection ID is used in both GSM/UMTS and CDMA
+     * modes [1] indicating the network interface name for GSM/UMTS or CDMA [2]
+     * indicating the IP address for this interface for GSM/UMTS and NULL in the
+     * case of CDMA
+     *
+     * @param radioTechnology
+     *            indicates whether to setup connection on radio technology CDMA
+     *            (0) or GSM/UMTS (1)
+     * @param profile
+     *            Profile Number or NULL to indicate default profile
+     * @param apn
+     *            the APN to connect to if radio technology is GSM/UMTS.
+     *            Otherwise null for CDMA.
+     * @param user
+     *            the username for APN, or NULL
+     * @param password
+     *            the password for APN, or NULL
+     * @param result
+     *            Callback message
+     */
+    public void setupDataCall(String radioTechnology, String profile, String apn,
+            String user, String password, Message result);
+
+    /**
+     * Deactivate packet data connection
+     *
+     * @param cid
+     *            The connection ID
+     * @param result
+     *            Callback message is empty on completion
+     */
+    public void deactivateDataCall(int cid, Message result);
+
+    /**
+     * Activate or deactivate cell broadcast SMS.
+     *
+     * @param activate
+     *            0 = activate, 1 = deactivate
+     * @param result
+     *            Callback message is empty on completion
+     */
+    public void activateCdmaBroadcastSms(int activate, Message result);
+
+    /**
+     * Configure cdma cell broadcast SMS.
+     *
+     * @param result
+     *            Callback message is empty on completion
+     */
+    public void setCdmaBroadcastConfig(int[] configValuesArray, Message result);
+
+    /**
+     * Query the current configuration of cdma cell broadcast SMS.
+     *
+     * @param result
+     *            Callback message contains the configuration from the modem on completion
+     */
+    public void getCdmaBroadcastConfig(Message result);
 }
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index ead49bf..86ceb89 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -19,8 +19,8 @@
 /**
  * {@hide}
  */
-public abstract class Connection
-{
+public abstract class Connection {
+
     // Number presentation type for caller id display
     public static int PRESENTATION_ALLOWED = 1;    // normal
     public static int PRESENTATION_RESTRICTED = 2; // block by user
@@ -42,7 +42,7 @@
         INCOMING_REJECTED,  /* an incoming call that was rejected */
         POWER_OFF,          /* radio is turned off explicitly */
         OUT_OF_SERVICE,     /* out of service */
-        SIM_ERROR,          /* No SIM, SIM locked, or other SIM error */
+        ICC_ERROR,          /* No ICC, ICC locked, or other ICC error */
         CALL_BARRED,        /* call was blocked by call barrring */
         FDN_BLOCKED,        /* call was blocked by fixed dial number */
         CS_RESTRICTED,      /* call was blocked by restricted all voice access */
@@ -54,7 +54,7 @@
 
     /* Instance Methods */
 
-    /** 
+    /**
      * Gets address (e.g., phone number) associated with connection
      * TODO: distinguish reasons for unavailablity
      *
@@ -92,7 +92,7 @@
     public abstract long getDisconnectTime();
 
     /**
-     * returns the number of milliseconds the call has been connected, 
+     * returns the number of milliseconds the call has been connected,
      * or 0 if the call has never connected.
      * If the call is still connected, then returns the elapsed
      * time since connect
@@ -113,8 +113,8 @@
     public abstract DisconnectCause getDisconnectCause();
 
     /**
-     * Returns true of this connection originated elsewhere 
-     * ("MT" or mobile terminated; another party called this terminal) 
+     * Returns true of this connection originated elsewhere
+     * ("MT" or mobile terminated; another party called this terminal)
      * or false if this call originated here (MO or mobile originated)
      */
     public abstract boolean isIncoming();
@@ -122,32 +122,30 @@
     /**
      * If this Connection is connected, then it is associated with
      * a Call.
-     * 
+     *
      * Returns getCall().getState() or Call.State.IDLE if not
      * connected
      */
-    public Call.State getState()
-    {
+    public Call.State getState() {
         Call c;
 
         c = getCall();
 
-        if (c == null) { 
+        if (c == null) {
             return Call.State.IDLE;
         } else {
             return c.getState();
         }
     }
-    
+
     /**
      * isAlive()
-     * 
+     *
      * @return true if the connection isn't disconnected
      * (could be active, holding, ringing, dialing, etc)
      */
     public boolean
-    isAlive()
-    {
+    isAlive() {
         return getState().isAlive();
     }
 
@@ -155,29 +153,26 @@
      * Returns true if Connection is connected and is INCOMING or WAITING
      */
     public boolean
-    isRinging()
-    {
+    isRinging() {
         return getState().isRinging();
     }
 
     /**
-     * 
+     *
      * @return the userdata set in setUserData()
      */
-    public Object getUserData()
-    {
+    public Object getUserData() {
         return userData;
     }
 
     /**
-     * 
+     *
      * @param userdata user can store an any userdata in the Connection object.
      */
-    public void setUserData(Object userdata)
-    {
+    public void setUserData(Object userdata) {
         this.userData = userdata;
     }
-    
+
     /**
      * Hangup individual Connection
      */
@@ -191,16 +186,16 @@
     public abstract void separate() throws CallStateException;
 
     public enum PostDialState {
-        NOT_STARTED,    /* The post dial string playback hasn't 
-                           been started, or this call is not yet 
+        NOT_STARTED,    /* The post dial string playback hasn't
+                           been started, or this call is not yet
                            connected, or this is an incoming call */
         STARTED,        /* The post dial string playback has begun */
-        WAIT,           /* The post dial string playback is waiting for a 
+        WAIT,           /* The post dial string playback is waiting for a
                            call to proceedAfterWaitChar() */
-        WILD,           /* The post dial string playback is waiting for a 
+        WILD,           /* The post dial string playback is waiting for a
                            call to proceedAfterWildChar() */
         COMPLETE,       /* The post dial string playback is complete */
-        CANCELLED       /* The post dial string playback was cancelled 
+        CANCELLED       /* The post dial string playback was cancelled
                            with cancelPostDial() */
     }
 
@@ -215,7 +210,7 @@
     /**
      * See Phone.setOnPostDialWaitCharacter()
      */
-     
+
     public abstract void proceedAfterWaitChar();
 
     /**
@@ -232,5 +227,5 @@
      * @return one of PRESENTATION_*
      */
     public abstract int getNumberPresentation();
-    
+
 }
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
new file mode 100644
index 0000000..6e9d1ab
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * {@hide}
+ */
+public abstract class DataConnection extends Handler {
+
+    // the inherited class
+
+    public enum State {
+        ACTIVE, /* has active data connection */
+        ACTIVATING, /* during connecting process */
+        INACTIVE; /* has empty data connection */
+
+        public String toString() {
+            switch (this) {
+            case ACTIVE:
+                return "active";
+            case ACTIVATING:
+                return "setting up";
+            default:
+                return "inactive";
+            }
+        }
+
+        public boolean isActive() {
+            return this == ACTIVE;
+        }
+
+        public boolean isInactive() {
+            return this == INACTIVE;
+        }
+    }
+
+    public enum FailCause {
+        NONE,
+        BAD_APN,
+        BAD_PAP_SECRET,
+        BARRED,
+        USER_AUTHENTICATION,
+        SERVICE_OPTION_NOT_SUPPORTED,
+        SERVICE_OPTION_NOT_SUBSCRIBED,
+        SIM_LOCKED,
+        RADIO_OFF,
+        NO_SIGNAL,
+        NO_DATA_PLAN,
+        RADIO_NOT_AVAILABLE,
+        SUSPENED_TEMPORARY,
+        RADIO_ERROR_RETRY,
+        UNKNOWN;
+
+        public boolean isPermanentFail() {
+            return (this == RADIO_OFF);
+        }
+
+        public String toString() {
+            switch (this) {
+            case NONE:
+                return "no error";
+            case BAD_APN:
+                return "bad apn";
+            case BAD_PAP_SECRET:
+                return "bad pap secret";
+            case BARRED:
+                return "barred";
+            case USER_AUTHENTICATION:
+                return "error user autentication";
+            case SERVICE_OPTION_NOT_SUPPORTED:
+                return "data not supported";
+            case SERVICE_OPTION_NOT_SUBSCRIBED:
+                return "datt not subcribed";
+            case SIM_LOCKED:
+                return "sim locked";
+            case RADIO_OFF:
+                return "radio is off";
+            case NO_SIGNAL:
+                return "no signal";
+            case NO_DATA_PLAN:
+                return "no data plan";
+            case RADIO_NOT_AVAILABLE:
+                return "radio not available";
+            case SUSPENED_TEMPORARY:
+                return "suspend temporary";
+            case RADIO_ERROR_RETRY:
+                return "transient radio error";
+            default:
+                return "unknown data error";
+            }
+        }
+    }
+
+    // ***** Event codes
+    protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 1;
+    protected static final int EVENT_GET_LAST_FAIL_DONE = 2;
+    protected static final int EVENT_LINK_STATE_CHANGED = 3;
+    protected static final int EVENT_DEACTIVATE_DONE = 4;
+    protected static final int EVENT_FORCE_RETRY = 5;
+
+    //***** Tag IDs for EventLog
+    protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
+
+
+    //***** Member Variables
+    protected PhoneBase phone;
+    protected Message onConnectCompleted;
+    protected Message onDisconnect;
+    protected int cid;
+    protected String interfaceName;
+    protected String ipAddress;
+    protected String gatewayAddress;
+    protected String[] dnsServers;
+    protected State state;
+    protected long createTime;
+    protected long lastFailTime;
+    protected FailCause lastFailCause;
+    protected static final String NULL_IP = "0.0.0.0";
+    Object userData;
+
+    // receivedDisconnectReq is set when disconnect during activation
+    protected boolean receivedDisconnectReq;
+
+    /* Instance Methods */
+    protected abstract void onSetupConnectionCompleted(AsyncResult ar);
+
+    protected abstract void onDeactivated(AsyncResult ar);
+
+    protected abstract void disconnect(Message msg);
+
+    protected abstract void notifyFail(FailCause cause, Message onCompleted);
+
+    protected abstract void notifyDisconnect(Message msg);
+
+    protected abstract void onLinkStateChanged(DataLink.LinkState linkState);
+
+    protected abstract FailCause getFailCauseFromRequest(int rilCause);
+
+    public abstract String toString();
+
+    protected abstract void log(String s);
+
+
+   //***** Constructor
+    protected DataConnection(PhoneBase phone) {
+        super();
+        this.phone = phone;
+        onConnectCompleted = null;
+        onDisconnect = null;
+        this.cid = -1;
+        receivedDisconnectReq = false;
+        this.dnsServers = new String[2];
+
+        clearSettings();
+    }
+
+    protected void setHttpProxy(String httpProxy, String httpPort) {
+        if (httpProxy == null || httpProxy.length() == 0) {
+            phone.setSystemProperty("net.gprs.http-proxy", null);
+            return;
+        }
+
+        if (httpPort == null || httpPort.length() == 0) {
+            httpPort = "8080";     // Default to port 8080
+        }
+
+        phone.setSystemProperty("net.gprs.http-proxy",
+                "http://" + httpProxy + ":" + httpPort + "/");
+    }
+
+    public String getInterface() {
+        return interfaceName;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public String getGatewayAddress() {
+        return gatewayAddress;
+    }
+
+    public String[] getDnsServers() {
+        return dnsServers;
+    }
+
+    public void clearSettings() {
+        log("DataConnection.clearSettings()");
+
+        this.state = State.INACTIVE;
+        this.createTime = -1;
+        this.lastFailTime = -1;
+        this.lastFailCause = FailCause.NONE;
+
+        receivedDisconnectReq = false;
+        onConnectCompleted = null;
+        interfaceName = null;
+        ipAddress = null;
+        gatewayAddress = null;
+        dnsServers[0] = null;
+        dnsServers[1] = null;
+    }
+
+    protected void onGetLastFailCompleted(AsyncResult ar) {
+        if (receivedDisconnectReq) {
+            // Don't bother reporting the error if there's already a
+            // pending disconnect request, since DataConnectionTracker
+            // has already updated its state.
+            notifyDisconnect(onDisconnect);
+        } else {
+            FailCause cause = FailCause.UNKNOWN;
+
+            if (ar.exception == null) {
+                int rilFailCause = ((int[]) (ar.result))[0];
+                cause = getFailCauseFromRequest(rilFailCause);
+            }
+            notifyFail(cause, onConnectCompleted);
+        }
+    }
+
+    protected void onForceRetry() {
+        if (receivedDisconnectReq) {
+            notifyDisconnect(onDisconnect);
+        } else {
+            notifyFail(FailCause.RADIO_ERROR_RETRY, onConnectCompleted);
+        }
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+
+        log("DataConnection.handleMessage()");
+
+        switch (msg.what) {
+
+        case EVENT_SETUP_DATA_CONNECTION_DONE:
+            onSetupConnectionCompleted((AsyncResult) msg.obj);
+            break;
+
+        case EVENT_FORCE_RETRY:
+            onForceRetry();
+            break;
+
+        case EVENT_GET_LAST_FAIL_DONE:
+            onGetLastFailCompleted((AsyncResult) msg.obj);
+            break;
+
+        case EVENT_LINK_STATE_CHANGED:
+            ar = (AsyncResult) msg.obj;
+            DataLink.LinkState ls  = (DataLink.LinkState) ar.result;
+            onLinkStateChanged(ls);
+            break;
+
+        case EVENT_DEACTIVATE_DONE:
+            onDeactivated((AsyncResult) msg.obj);
+            break;
+        }
+    }
+
+    public State getState() {
+        log("DataConnection.getState()");
+        return state;
+    }
+
+    public long getConnectionTime() {
+        log("DataConnection.getConnectionTime()");
+        return createTime;
+    }
+
+    public long getLastFailTime() {
+        log("DataConnection.getLastFailTime()");
+        return lastFailTime;
+    }
+
+    public FailCause getLastFailCause() {
+        log("DataConnection.getLastFailCause()");
+        return lastFailCause;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
new file mode 100644
index 0000000..5b826b2
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.INetStatService;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Log;
+
+/**
+ * {@hide}
+ *
+ */
+public abstract class DataConnectionTracker extends Handler {
+    private static final boolean DBG = true;
+
+    /**
+     * IDLE: ready to start data connection setup, default state
+     * INITING: state of issued setupDefaultPDP() but not finish yet
+     * CONNECTING: state of issued startPppd() but not finish yet
+     * SCANNING: data connection fails with one apn but other apns are available
+     *           ready to start data connection on other apns (before INITING)
+     * CONNECTED: IP connection is setup
+     * DISCONNECTING: Connection.disconnect() has been called, but PDP
+     *                context is not yet deactivated
+     * FAILED: data connection fail for all apns settings
+     *
+     * getDataConnectionState() maps State to DataState
+     *      FAILED or IDLE : DISCONNECTED
+     *      INITING or CONNECTING or SCANNING: CONNECTING
+     *      CONNECTED : CONNECTED or DISCONNECTING
+     */
+    public enum State {
+        IDLE,
+        INITING,
+        CONNECTING,
+        SCANNING,
+        CONNECTED,
+        DISCONNECTING,
+        FAILED
+    }
+
+    public enum Activity {
+        NONE,
+        DATAIN,
+        DATAOUT,
+        DATAINANDOUT
+    }
+
+    //***** Event Codes
+    protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
+    protected static final int EVENT_RADIO_AVAILABLE = 3;
+    protected static final int EVENT_RECORDS_LOADED = 4;
+    protected static final int EVENT_TRY_SETUP_DATA = 5;
+    protected static final int EVENT_DATA_STATE_CHANGED = 6;
+    protected static final int EVENT_POLL_PDP = 7;
+    protected static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
+    protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
+    protected static final int EVENT_VOICE_CALL_STARTED = 14;
+    protected static final int EVENT_VOICE_CALL_ENDED = 15;
+    protected static final int EVENT_GPRS_DETACHED = 19;
+    protected static final int EVENT_LINK_STATE_CHANGED = 20;
+    protected static final int EVENT_ROAMING_ON = 21;
+    protected static final int EVENT_ROAMING_OFF = 22;
+    protected static final int EVENT_ENABLE_NEW_APN = 23;
+    protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
+    protected static final int EVENT_DISCONNECT_DONE = 25;
+    protected static final int EVENT_GPRS_ATTACHED = 26;
+    protected static final int EVENT_START_NETSTAT_POLL = 27;
+    protected static final int EVENT_START_RECOVERY = 28;
+    protected static final int EVENT_APN_CHANGED = 29;
+    protected static final int EVENT_CDMA_DATA_DETACHED = 30;
+    protected static final int EVENT_NV_READY = 31;
+    protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
+    protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
+
+    //***** Constants
+    protected static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
+
+    /** Cap out with 1 hour retry interval. */
+    protected static final int RECONNECT_DELAY_MAX_MILLIS = 60 * 60 * 1000;
+
+    /** Slow poll when attempting connection recovery. */
+    protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
+    /** Default ping deadline, in seconds. */
+    protected final int DEFAULT_PING_DEADLINE = 5;
+    /** Default max failure count before attempting to network re-registration. */
+    protected final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
+
+    /**
+     * After detecting a potential connection problem, this is the max number
+     * of subsequent polls before attempting a radio reset.  At this point,
+     * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
+     * poll for about 2 more minutes.
+     */
+    protected static final int NO_RECV_POLL_LIMIT = 24;
+
+    // 1 sec. default polling interval when screen is on.
+    protected static final int POLL_NETSTAT_MILLIS = 1000;
+    // 10 min. default polling interval when screen is off.
+    protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
+    // 2 min for round trip time
+    protected static final int POLL_LONGEST_RTT = 120 * 1000;
+    // 10 for packets without ack
+    protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
+    // how long to wait before switching back to default APN
+    protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
+    // system property that can override the above value
+    protected static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
+    // represents an invalid IP address
+    protected static final String NULL_IP = "0.0.0.0";
+
+
+    // member variables
+    protected PhoneBase phone;
+    protected Activity activity = Activity.NONE;
+    protected State state = State.IDLE;
+    protected Handler mDataConnectionTracker = null;
+
+
+    protected INetStatService netstat;
+    protected long txPkts, rxPkts, sentSinceLastRecv;
+    protected int netStatPollPeriod;
+    protected int mNoRecvPollCount = 0;
+    protected boolean netStatPollEnabled = false;
+
+    // wifi connection status will be updated by sticky intent
+    protected boolean mIsWifiConnected = false;
+
+    /** Intent sent when the reconnect alarm fires. */
+    protected PendingIntent mReconnectIntent = null;
+    
+    /** CID of active data connection */
+    protected int cidActive;
+
+   /**
+     * Default constructor
+     */
+    protected DataConnectionTracker(PhoneBase phone) {
+        super();
+        this.phone = phone;
+    }
+
+    public Activity getActivity() {
+        return activity;
+    }
+
+    public State getState() {
+        return state;
+    }
+
+    public String getStateInString() {
+        switch (state) {
+            case IDLE:          return "IDLE";
+            case INITING:       return "INIT";
+            case CONNECTING:    return "CING";
+            case SCANNING:      return "SCAN";
+            case CONNECTED:     return "CNTD";
+            case DISCONNECTING: return "DING";
+            case FAILED:        return "FAIL";
+            default:            return "ERRO";
+        }
+    }
+
+    /**
+     * The data connection is expected to be setup while device
+     *  1. has Icc card
+     *  2. registered for data service
+     *  3. user doesn't explicitly disable data service
+     *  4. wifi is not on
+     *
+     * @return false while no data connection if all above requirements are met.
+     */
+    public abstract boolean isDataConnectionAsDesired();
+
+    //The data roaming setting is now located in the shared preferences.
+    //  See if the requested preference value is the same as that stored in
+    //  the shared values.  If it is not, then update it.
+    public void setDataOnRoamingEnabled(boolean enabled) {
+        if (getDataOnRoamingEnabled() != enabled) {
+            Settings.Secure.putInt(phone.getContext().getContentResolver(),
+                Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
+        }
+        Message roamingMsg = phone.getServiceState().getRoaming() ?
+            obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
+        sendMessage(roamingMsg);
+    }
+
+    //Retrieve the data roaming setting from the shared preferences.
+    public boolean getDataOnRoamingEnabled() {
+        try {
+            return Settings.Secure.getInt(phone.getContext().getContentResolver(),
+                Settings.Secure.DATA_ROAMING) > 0;
+        } catch (SettingNotFoundException snfe) {
+            return false;
+        }
+    }
+
+    // abstract handler methods
+    protected abstract void onTrySetupData();
+    protected abstract void onRoamingOff();
+    protected abstract void onRoamingOn();
+    protected abstract void onRadioAvailable();
+    protected abstract void onRadioOffOrNotAvailable();
+    protected abstract void onDataSetupComplete(AsyncResult ar);
+    protected abstract void onDisconnectDone(AsyncResult ar);
+    protected abstract void onVoiceCallStarted();
+    protected abstract void onVoiceCallEnded();
+
+  //***** Overridden from Handler
+    public void handleMessage (Message msg) {
+        switch (msg.what) {
+
+            case EVENT_TRY_SETUP_DATA:
+                onTrySetupData();
+                break;
+
+            case EVENT_ROAMING_OFF:
+                onRoamingOff();
+                break;
+
+            case EVENT_ROAMING_ON:
+                onRoamingOn();
+                break;
+
+            case EVENT_RADIO_AVAILABLE:
+                onRadioAvailable();
+                break;
+
+            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
+                onRadioOffOrNotAvailable();
+                break;
+
+            case EVENT_DATA_SETUP_COMPLETE:
+                cidActive = msg.arg1;
+                onDataSetupComplete((AsyncResult) msg.obj);
+                break;
+
+            case EVENT_DISCONNECT_DONE:
+                onDisconnectDone((AsyncResult) msg.obj);
+                break;
+
+            case EVENT_VOICE_CALL_STARTED:
+                onVoiceCallStarted();
+                break;
+
+            case EVENT_VOICE_CALL_ENDED:
+                onVoiceCallEnded();
+                break;
+
+            default:
+                Log.e("DATA", "Unidentified event = " + msg.what);
+                break;
+        }
+    }
+
+    /**
+     * Simply tear down data connections due to radio off 
+     * and don't setup again.
+     */
+    public abstract void cleanConnectionBeforeRadioOff();
+
+    /**
+     * Report the current state of data connectivity (enabled or disabled)
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public abstract boolean getDataEnabled();
+
+    /**
+     * Report on whether data connectivity is enabled
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public abstract boolean getAnyDataEnabled();
+
+    /**
+     * Prevent mobile data connections from being established,
+     * or once again allow mobile data connections. If the state
+     * toggles, then either tear down or set up data, as
+     * appropriate to match the new state.
+     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+     * @return {@code true} if the operation succeeded
+     */
+    public abstract boolean setDataEnabled(boolean enable);
+
+    protected abstract void startNetStatPoll();
+
+    protected abstract void stopNetStatPoll();
+
+    protected abstract void restartRadio();
+
+    protected abstract void log(String s);
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataLink.java b/telephony/java/com/android/internal/telephony/DataLink.java
similarity index 82%
rename from telephony/java/com/android/internal/telephony/gsm/DataLink.java
rename to telephony/java/com/android/internal/telephony/DataLink.java
index b822ab4..8132d91 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataLink.java
+++ b/telephony/java/com/android/internal/telephony/DataLink.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.os.Handler;
 import android.os.Registrant;
@@ -24,14 +24,13 @@
  *
  * {@hide}
  */
-abstract class DataLink extends Handler implements DataLinkInterface {
+public abstract class DataLink extends Handler implements DataLinkInterface {
 
     /** Registrant for link status change notifications. */
-    Registrant mLinkChangeRegistrant;
-    
+    protected Registrant mLinkChangeRegistrant;
     protected DataConnectionTracker dataConnection;
 
-    DataLink(DataConnectionTracker dc) {
+    protected DataLink(DataConnectionTracker dc) {
         dataConnection = dc;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataLinkInterface.java b/telephony/java/com/android/internal/telephony/DataLinkInterface.java
similarity index 90%
rename from telephony/java/com/android/internal/telephony/gsm/DataLinkInterface.java
rename to telephony/java/com/android/internal/telephony/DataLinkInterface.java
index bca63f2..e8148a8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataLinkInterface.java
+++ b/telephony/java/com/android/internal/telephony/DataLinkInterface.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.database.Cursor;
 import android.os.Handler;
@@ -24,7 +24,7 @@
  *
  * {@hide}
  */
-interface DataLinkInterface {
+public interface DataLinkInterface {
     /**
      * Link state enumeration.
      *
@@ -35,21 +35,21 @@
         LINK_DOWN,
         LINK_EXITED
     }
-    
+
     /** Normal exit */
     final static int EXIT_OK = 0;
     /** Open failed */
     final static int EXIT_OPEN_FAILED = 7;
-    
+
     /**
      * Sets the handler for link state change events.
-     * 
+     *
      * @param h Handler
      * @param what User-defined message code
      * @param obj User object
      */
     void setOnLinkChange(Handler h, int what, Object obj);
-    
+
     /**
      * Sets up the data link.
      */
@@ -59,14 +59,14 @@
      * Tears down the data link.
      */
     void disconnect();
-    
+
     /**
-     * Returns the exit code for a data link failure. 
+     * Returns the exit code for a data link failure.
      *
      * @return exit code
      */
     int getLastLinkExitCode();
-    
+
     /**
      * Sets password information that may be required by the data link
      * (eg, PAP secrets).
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 81ef623..79b4afe 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -33,7 +33,7 @@
     private static final boolean DBG = true;
     private ITelephonyRegistry mRegistry;
 
-    /*package*/ 
+    /*package*/
     DefaultPhoneNotifier() {
         mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                     "telephony.registry"));
@@ -94,7 +94,7 @@
 
     public void notifyDataConnection(Phone sender, String reason) {
         try {
-            mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()), 
+            mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),
                     sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
                     sender.getInterfaceName(null));
         } catch (RemoteException ex) {
@@ -119,7 +119,7 @@
             // system process is dead
         }
     }
-    
+
     private void log(String s) {
         Log.d(LOG_TAG, "[PhoneNotifier] " + s);
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java b/telephony/java/com/android/internal/telephony/DriverCall.java
similarity index 84%
rename from telephony/java/com/android/internal/telephony/gsm/DriverCall.java
rename to telephony/java/com/android/internal/telephony/DriverCall.java
index aab885a..0d9a60f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java
+++ b/telephony/java/com/android/internal/telephony/DriverCall.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
-
+package com.android.internal.telephony;
+//import com.android.internal.telephony.*;
 import android.util.Log;
 import java.lang.Comparable;
 import android.telephony.PhoneNumberUtils;
@@ -24,10 +23,9 @@
 /**
  * {@hide}
  */
-public class DriverCall implements Comparable
-{
-    static final String LOG_TAG = "GSM";
-    
+public class DriverCall implements Comparable {
+    static final String LOG_TAG = "RILB";
+
     public enum State {
         ACTIVE,
         HOLDING,
@@ -46,13 +44,15 @@
     public String number;
     public int TOA;
     public boolean isVoice;
+    public boolean isVoicePrivacy;
     public int als;
     public int numberPresentation;
-  
+    public String name;
+    public int namePresentation;
+
     /** returns null on error */
     static DriverCall
-    fromCLCCLine(String line)
-    {
+    fromCLCCLine(String line) {
         DriverCall ret = new DriverCall();
 
         //+CLCC: 1,0,2,0,0,\"+18005551212\",145
@@ -66,10 +66,10 @@
 
             ret.isVoice = (0 == p.nextInt());
             ret.isMpty = p.nextBoolean();
-            
+
             // use ALLOWED as default presentation while parsing CLCC
             ret.numberPresentation = Connection.PRESENTATION_ALLOWED;
-            
+
             if (p.hasMore()) {
                 // Some lame implementations return strings
                 // like "NOT AVAILABLE" in the CLCC line
@@ -98,24 +98,25 @@
     }
 
     public
-    DriverCall()
-    {
+    DriverCall() {
     }
 
     public String
-    toString()
-    {
+    toString() {
         return "id=" + index + ","
-                + (isMT ? "mt" : "mo") + ","
                 + state + ","
-                + (isVoice ? "voice" : "no_voc") + ","
+                + "toa=" + TOA + ","
                 + (isMpty ? "conf" : "norm") + ","
-                + TOA + "," + als + ",cli " + numberPresentation;
+                + (isMT ? "mt" : "mo") + ","
+                + als + ","
+                + (isVoice ? "voc" : "nonvoc") + ","
+                + (isVoicePrivacy ? "evp" : "noevp") + ","
+                /*+ "number=" + number */ + ",cli=" + numberPresentation + ","
+                /*+ "name="+ name */ + "," + namePresentation;
     }
 
     public static State
-    stateFromCLCC(int state) throws ATParseEx
-    {
+    stateFromCLCC(int state) throws ATParseEx {
         switch(state) {
             case 0: return State.ACTIVE;
             case 1: return State.HOLDING;
@@ -127,7 +128,7 @@
                 throw new ATParseEx("illegal call state " + state);
         }
     }
-    
+
     public static int
     presentationFromCLIP(int cli) throws ATParseEx
     {
@@ -141,12 +142,11 @@
         }
     }
 
-    //***** Comparable Implementation 
+    //***** Comparable Implementation
 
     /** For sorting by index */
     public int
-    compareTo (Object o)
-    {
+    compareTo (Object o) {
         DriverCall dc;
 
         dc = (DriverCall)o;
diff --git a/telephony/java/com/android/internal/telephony/gsm/EncodeException.java b/telephony/java/com/android/internal/telephony/EncodeException.java
similarity index 77%
rename from telephony/java/com/android/internal/telephony/gsm/EncodeException.java
rename to telephony/java/com/android/internal/telephony/EncodeException.java
index d546cef..0436ba0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/EncodeException.java
+++ b/telephony/java/com/android/internal/telephony/EncodeException.java
@@ -14,25 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class EncodeException extends Exception
-{
-    public EncodeException()
-    {
+public class EncodeException extends Exception {
+    public EncodeException() {
         super();
     }
-  
-    public EncodeException(String s)
-    {
+
+    public EncodeException(String s) {
         super(s);
     }
 
-    public EncodeException(char c)
-    {
+    public EncodeException(char c) {
         super("Unencodable char: '" + c + "'");
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
similarity index 93%
rename from telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java
rename to telephony/java/com/android/internal/telephony/GsmAlphabet.java
index df34897..8f4c69c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import android.telephony.gsm.SmsMessage;
+import android.telephony.SmsMessage;
 import android.util.SparseIntArray;
 
 import android.util.Log;
@@ -28,16 +28,15 @@
  *
  * {@hide}
  */
-public class GsmAlphabet
-{
+public class GsmAlphabet {
     static final String LOG_TAG = "GSM";
-    
+
 
 
     //***** Constants
 
     /**
-     * This escapes extended characters, and when present indicates that the 
+     * This escapes extended characters, and when present indicates that the
      * following character should
      * be looked up in the "extended" table
      *
@@ -55,8 +54,7 @@
      * should follow GSM_EXTENDED_ESCAPE in the GSM alphabet string
      */
     public static int
-    charToGsm(char c)
-    {
+    charToGsm(char c) {
         try {
             return charToGsm(c, false);
         } catch (EncodeException ex) {
@@ -67,7 +65,7 @@
 
     /**
      * char to GSM alphabet char
-     * @param throwException If true, throws EncodeException on invalid char. 
+     * @param throwException If true, throws EncodeException on invalid char.
      *   If false, returns GSM alphabet ' ' char.
      *
      * Returns GSM_EXTENDED_ESCAPE if this character is in the extended table
@@ -76,10 +74,9 @@
      */
 
     public static int
-    charToGsm(char c, boolean throwException) throws EncodeException
-    {
+    charToGsm(char c, boolean throwException) throws EncodeException {
         int ret;
-        
+
         ret = charToGsm.get(c, -1);
 
         if (ret == -1) {
@@ -99,7 +96,7 @@
         return ret;
 
     }
-    
+
 
     /**
      * char to extended GSM alphabet char
@@ -110,10 +107,9 @@
      *
      */
     public static int
-    charToGsmExtended(char c)
-    {
+    charToGsmExtended(char c) {
         int ret;
-        
+
         ret = charToGsmExtended.get(c, -1);
 
         if (ret == -1) {
@@ -124,34 +120,32 @@
     }
 
     /**
-     * Converts a character in the GSM alphabet into a char 
+     * Converts a character in the GSM alphabet into a char
      *
      * if GSM_EXTENDED_ESCAPE is passed, 0xffff is returned. In this case,
-     * the following character in the stream should be decoded with 
+     * the following character in the stream should be decoded with
      * gsmExtendedToChar()
      *
      * If an unmappable value is passed (one greater than 127), ' ' is returned
      */
 
     public static char
-    gsmToChar(int gsmChar)
-    {
+    gsmToChar(int gsmChar) {
         return (char)gsmToChar.get(gsmChar, ' ');
     }
-    
+
     /**
-     * Converts a character in the extended GSM alphabet into a char 
+     * Converts a character in the extended GSM alphabet into a char
      *
      * if GSM_EXTENDED_ESCAPE is passed, ' ' is returned since no second
      * extension page has yet been defined (see Note 1 in table 6.2.1.1 of
      * TS 23.038 v7.00)
-     *     
+     *
      * If an unmappable value is passed , ' ' is returned
      */
 
     public static char
-    gsmExtendedToChar(int gsmChar)
-    {
+    gsmExtendedToChar(int gsmChar) {
         int ret;
 
         ret = gsmExtendedToChar.get(gsmChar, -1);
@@ -205,7 +199,7 @@
     }
 
     /**
-     * Converts a String into a byte array containing 
+     * Converts a String into a byte array containing
      * the 7-bit packed GSM Alphabet representation of the string.
      *
      * Unencodable chars are encoded as spaces
@@ -224,7 +218,7 @@
     }
 
     /**
-     * Converts a String into a byte array containing 
+     * Converts a String into a byte array containing
      * the 7-bit packed GSM Alphabet representation of the string.
      *
      * Byte 0 in the returned byte array is the count of septets used
@@ -238,7 +232,7 @@
      *  enforced maximum.
      * @param startingBitOffset the number of padding bits to put before
      *  the start of the first septet at the begining of the array
-     * @param throwException If true, throws EncodeException on invalid char. 
+     * @param throwException If true, throws EncodeException on invalid char.
      *   If false, replaces unencodable char with GSM alphabet space char.
      *
      * @throws EncodeException if String is too large to encode
@@ -294,27 +288,26 @@
      * @param bitOffset the bit offset that the septet should be packed at
      *                  (septet index * 7)
      */
-    private static void 
-    packSmsChar(byte[] packedChars, int bitOffset, int value)
-    {
+    private static void
+    packSmsChar(byte[] packedChars, int bitOffset, int value) {
         int byteOffset = bitOffset / 8;
         int shift = bitOffset % 8;
 
         packedChars[++byteOffset] |= value << shift;
 
         if (shift > 1) {
-        	packedChars[++byteOffset] = (byte)(value >> (8 - shift));
-        }    	
+            packedChars[++byteOffset] = (byte)(value >> (8 - shift));
+        }
     }
 
     /**
-     * Convert a GSM alphabet 7 bit packed string (SMS string) into a 
+     * Convert a GSM alphabet 7 bit packed string (SMS string) into a
      * {@link java.lang.String}.
      *
      * See TS 23.038 6.1.2.1 for SMS Character Packing
      *
      * @param pdu the raw data from the pdu
-     * @param offset the byte offset of 
+     * @param offset the byte offset of
      * @param lengthSeptets string length in septets, not bytes
      * @return String representation or null on decoding exception
      */
@@ -324,27 +317,26 @@
     }
 
     /**
-     * Convert a GSM alphabet 7 bit packed string (SMS string) into a 
+     * Convert a GSM alphabet 7 bit packed string (SMS string) into a
      * {@link java.lang.String}.
      *
      * See TS 23.038 6.1.2.1 for SMS Character Packing
      *
      * @param pdu the raw data from the pdu
-     * @param offset the byte offset of 
+     * @param offset the byte offset of
      * @param lengthSeptets string length in septets, not bytes
      * @param numPaddingBits the number of padding bits before the start of the
      *  string in the first byte
      * @return String representation or null on decoding exception
      */
     public static String gsm7BitPackedToString(byte[] pdu, int offset,
-            int lengthSeptets, int numPaddingBits)
-    {
+            int lengthSeptets, int numPaddingBits) {
         StringBuilder ret = new StringBuilder(lengthSeptets);
         boolean prevCharWasEscape;
-        
+
         try {
             prevCharWasEscape = false;
-            
+
             for (int i = 0 ; i < lengthSeptets ; i++) {
                 int bitOffset = (7 * i) + numPaddingBits;
 
@@ -381,15 +373,14 @@
 
 
     /**
-     * Convert a GSM alphabet string that's stored in 8-bit unpacked 
+     * Convert a GSM alphabet string that's stored in 8-bit unpacked
      * format (as it often appears in SIM records) into a String
      *
      * Field may be padded with trailing 0xff's. The decode stops
      * at the first 0xff encountered.
      */
     public static String
-    gsm8BitUnpackedToString(byte[] data, int offset, int length)
-    {
+    gsm8BitUnpackedToString(byte[] data, int offset, int length) {
         boolean prevWasEscape;
         StringBuilder ret = new StringBuilder(length);
 
@@ -420,8 +411,8 @@
                 prevWasEscape = false;
             }
         }
-        
-        return ret.toString();    
+
+        return ret.toString();
     }
 
     /**
@@ -429,8 +420,7 @@
      * array
      */
     public static byte[]
-    stringToGsm8BitPacked(String s)
-    {
+    stringToGsm8BitPacked(String s) {
         byte[] ret;
 
         int septets = 0;
@@ -452,15 +442,14 @@
      *
      * Field is padded with 0xff's, string is truncated if necessary
      */
-     
+
     public static void
-    stringToGsm8BitUnpackedField(String s, byte dest[], int offset, int length)
-    {
+    stringToGsm8BitUnpackedField(String s, byte dest[], int offset, int length) {
         int outByteIndex = offset;
 
         // Septets are stored in byte-aligned octets
         for (int i = 0, sz = s.length()
-                ; i < sz && (outByteIndex - offset) < length 
+                ; i < sz && (outByteIndex - offset) < length
                 ; i++
         ) {
             char c = s.charAt(i);
@@ -475,7 +464,7 @@
 
                 dest[outByteIndex++] = GSM_EXTENDED_ESCAPE;
 
-        		v = GsmAlphabet.charToGsmExtended(c);
+                v = GsmAlphabet.charToGsmExtended(c);
             }
 
             dest[outByteIndex++] = (byte)v;
@@ -492,8 +481,7 @@
      * needed to represent this character. Counts unencodable char as 1 septet.
      */
     public static int
-    countGsmSeptets(char c)
-    {
+    countGsmSeptets(char c) {
         try {
             return countGsmSeptets(c, false);
         } catch (EncodeException ex) {
@@ -509,21 +497,20 @@
      * char. Otherwise, counts invalid char as 1 septet
      */
     public static int
-    countGsmSeptets(char c, boolean throwsException) throws EncodeException
-    {
-    	if (charToGsm.get(c, -1) != -1) {
-    		return 1;
-    	}
-    	
-    	if (charToGsmExtended.get(c, -1) != -1) {
-    		return 2;
-    	}
+    countGsmSeptets(char c, boolean throwsException) throws EncodeException {
+        if (charToGsm.get(c, -1) != -1) {
+            return 1;
+        }
+
+        if (charToGsmExtended.get(c, -1) != -1) {
+            return 2;
+        }
 
         if (throwsException) {
             throw new EncodeException(c);
-        } else {    
-        	// count as a space char
-        	return 1;
+        } else {
+            // count as a space char
+            return 1;
         }
     }
 
@@ -532,8 +519,7 @@
      * needed to represent this string. Counts unencodable char as 1 septet.
      */
     public static int
-    countGsmSeptets(CharSequence s)
-    {
+    countGsmSeptets(CharSequence s) {
         try {
             return countGsmSeptets(s, false);
         } catch (EncodeException ex) {
@@ -549,8 +535,7 @@
      * char. Otherwise, counts invalid char as 1 septet
      */
     public static int
-    countGsmSeptets(CharSequence s, boolean throwsException) throws EncodeException
-    {
+    countGsmSeptets(CharSequence s, boolean throwsException) throws EncodeException {
         int charIndex = 0;
         int sz = s.length();
         int count = 0;
@@ -559,9 +544,9 @@
             count += countGsmSeptets(s.charAt(charIndex), throwsException);
             charIndex++;
         }
-        
+
         return count;
-    }    
+    }
 
     /**
      * Returns the index into <code>s</code> of the first character
@@ -623,7 +608,7 @@
      * @return index of first character that won't fit, or the length
      *   of the entire string if everything fits
      */
-    public static int 
+    public static int
     findLimitIndex(String s, int start, int limit, int encodingType) throws EncodeException {
         if (encodingType == SmsMessage.ENCODING_7BIT) {
             return findGsmSeptetLimitIndex(s, start, limit);
@@ -643,10 +628,10 @@
     private static final SparseIntArray gsmToChar = new SparseIntArray();
     private static final SparseIntArray charToGsmExtended = new SparseIntArray();
     private static final SparseIntArray gsmExtendedToChar = new SparseIntArray();
-    
+
     static {
         int i = 0;
-        
+
         charToGsm.put('@', i++);
         charToGsm.put('\u00a3', i++);
         charToGsm.put('$', i++);
@@ -663,7 +648,7 @@
         charToGsm.put('\r', i++);
         charToGsm.put('\u00c5', i++);
         charToGsm.put('\u00e5', i++);
-        
+
         charToGsm.put('\u0394', i++);
         charToGsm.put('_', i++);
         charToGsm.put('\u03a6', i++);
@@ -680,7 +665,7 @@
         charToGsm.put('\u00e6', i++);
         charToGsm.put('\u00df', i++);
         charToGsm.put('\u00c9', i++);
-        
+
         charToGsm.put(' ', i++);
         charToGsm.put('!', i++);
         charToGsm.put('"', i++);
@@ -697,7 +682,7 @@
         charToGsm.put('-', i++);
         charToGsm.put('.', i++);
         charToGsm.put('/', i++);
-        
+
         charToGsm.put('0', i++);
         charToGsm.put('1', i++);
         charToGsm.put('2', i++);
@@ -714,7 +699,7 @@
         charToGsm.put('=', i++);
         charToGsm.put('>', i++);
         charToGsm.put('?', i++);
-        
+
         charToGsm.put('\u00a1', i++);
         charToGsm.put('A', i++);
         charToGsm.put('B', i++);
@@ -731,7 +716,7 @@
         charToGsm.put('M', i++);
         charToGsm.put('N', i++);
         charToGsm.put('O', i++);
-        
+
         charToGsm.put('P', i++);
         charToGsm.put('Q', i++);
         charToGsm.put('R', i++);
@@ -748,7 +733,7 @@
         charToGsm.put('\u0147', i++);
         charToGsm.put('\u00dc', i++);
         charToGsm.put('\u00a7', i++);
-        
+
         charToGsm.put('\u00bf', i++);
         charToGsm.put('a', i++);
         charToGsm.put('b', i++);
@@ -765,7 +750,7 @@
         charToGsm.put('m', i++);
         charToGsm.put('n', i++);
         charToGsm.put('o', i++);
-        
+
         charToGsm.put('p', i++);
         charToGsm.put('q', i++);
         charToGsm.put('r', i++);
@@ -782,8 +767,8 @@
         charToGsm.put('\u00f1', i++);
         charToGsm.put('\u00fc', i++);
         charToGsm.put('\u00e0', i++);
-        
-        
+
+
         charToGsmExtended.put('\f', 10);
         charToGsmExtended.put('^', 20);
         charToGsmExtended.put('{', 40);
@@ -794,12 +779,12 @@
         charToGsmExtended.put(']', 62);
         charToGsmExtended.put('|', 64);
         charToGsmExtended.put('\u20ac', 101);
-                
+
         int size = charToGsm.size();
         for (int j=0; j<size; j++) {
             gsmToChar.put(charToGsm.valueAt(j), charToGsm.keyAt(j));
         }
- 
+
         size = charToGsmExtended.size();
         for (int j=0; j<size; j++) {
             gsmExtendedToChar.put(charToGsmExtended.valueAt(j), charToGsmExtended.keyAt(j));
@@ -808,6 +793,6 @@
 
         sGsmSpaceChar = charToGsm.get(' ');
     }
-    
+
 
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl b/telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl
similarity index 88%
rename from telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl
rename to telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl
index 77033a7..f700dfe 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl
+++ b/telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl
@@ -14,27 +14,27 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import com.android.internal.telephony.gsm.AdnRecord;
+import com.android.internal.telephony.AdnRecord;
 
-import java.util.List;
 
-/** Interface for applications to access the SIM phone book.
+
+/** Interface for applications to access the ICC phone book.
  *
  * <p>The following code snippet demonstrates a static method to
- * retrieve the ISimPhoneBook interface from Android:</p>
- * <pre>private static ISimPhoneBook getSimPhoneBookInterface()
+ * retrieve the IIccPhoneBook interface from Android:</p>
+ * <pre>private static IIccPhoneBook getSimPhoneBookInterface()
             throws DeadObjectException {
     IServiceManager sm = ServiceManagerNative.getDefault();
-    ISimPhoneBook spb;
-    spb = ISimPhoneBook.Stub.asInterface(sm.getService("simphonebook"));
+    IIccPhoneBook spb;
+    spb = IIccPhoneBook.Stub.asInterface(sm.getService("iccphonebook"));
     return spb;
 }
  * </pre>
  */
 
-interface ISimPhoneBook {
+interface IIccPhoneBook {
 
     /**
      * Loads the AdnRecords in efid and returns them as a
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 00cbaf9..e74b9e4 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -39,9 +39,9 @@
     String getSubscriberId();
 
     /**
-     * Retrieves the serial number of the SIM, if applicable.
+     * Retrieves the serial number of the ICC, if applicable.
      */
-    String getSimSerialNumber();
+    String getIccSerialNumber();
 
     /**
      * Retrieves the phone number string for line 1.
@@ -53,13 +53,13 @@
      */
     String getLine1AlphaTag();
 
-	/**
-	 * Retrieves the voice mail number.
-	 */
+    /**
+     * Retrieves the voice mail number.
+     */
     String getVoiceMailNumber();
 
-	/**
-	 * Retrieves the alpha identifier associated with the voice mail number.
-	 */
+    /**
+     * Retrieves the alpha identifier associated with the voice mail number.
+     */
     String getVoiceMailAlphaTag();
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
similarity index 74%
rename from telephony/java/com/android/internal/telephony/gsm/ISms.aidl
rename to telephony/java/com/android/internal/telephony/ISms.aidl
index 904a54e..257f1e6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -14,20 +14,20 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.app.PendingIntent;
-import com.android.internal.telephony.gsm.SmsRawData;
+import com.android.internal.telephony.SmsRawData;
 
-/** Interface for applications to access the SIM phone book.
+/** Interface for applications to access the ICC phone book.
  *
  * <p>The following code snippet demonstrates a static method to
- * retrieve the ISimSms interface from Android:</p>
- * <pre>private static ISimSms getSimSmsInterface()
+ * retrieve the ISms interface from Android:</p>
+ * <pre>private static ISms getSmsInterface()
             throws DeadObjectException {
     IServiceManager sm = ServiceManagerNative.getDefault();
-    ISimSms ss;
-    ss = ISimSms.Stub.asInterface(sm.getService("isms"));
+    ISms ss;
+    ss = ISms.Stub.asInterface(sm.getService("isms"));
     return ss;
 }
  * </pre>
@@ -35,45 +35,45 @@
 
 interface ISms {
     /**
-     * Retrieves all messages currently stored on SIM.
+     * Retrieves all messages currently stored on ICC.
      *
-     * @return list of SmsRawData of all sms on SIM
+     * @return list of SmsRawData of all sms on ICC
      */
-     List<SmsRawData> getAllMessagesFromSimEf();
+     List<SmsRawData> getAllMessagesFromIccEf();
 
     /**
-     * Update the specified message on the SIM.
+     * Update the specified message on the ICC.
      *
      * @param messageIndex record index of message to update
-     * @param newStatus new message status (STATUS_ON_SIM_READ,
-     *                  STATUS_ON_SIM_UNREAD, STATUS_ON_SIM_SENT,
-     *                  STATUS_ON_SIM_UNSENT, STATUS_ON_SIM_FREE)
+     * @param newStatus new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
      * @param pdu the raw PDU to store
      * @return success or not
      *
      */
-     boolean updateMessageOnSimEf(int messageIndex, int newStatus,
+     boolean updateMessageOnIccEf(int messageIndex, int newStatus,
             in byte[] pdu);
 
     /**
-     * Copy a raw SMS PDU to the SIM.
+     * Copy a raw SMS PDU to the ICC.
      *
      * @param pdu the raw PDU to store
-     * @param status message status (STATUS_ON_SIM_READ, STATUS_ON_SIM_UNREAD,
-     *               STATUS_ON_SIM_SENT, STATUS_ON_SIM_UNSENT)
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
      * @return success or not
      *
      */
-    boolean copyMessageToSimEf(int status, in byte[] pdu, in byte[] smsc);
+    boolean copyMessageToIccEf(int status, in byte[] pdu, in byte[] smsc);
 
     /**
      * Send a SMS
      *
      * @param smsc the SMSC to send the message through, or NULL for the
-     *  defatult SMSC
+     *  default SMSC
      * @param pdu the raw PDU to send
      * @param sentIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
+     *  broadcast when the message is successfully sent, or failed.
      *  The result code will be <code>Activity.RESULT_OK<code> for success,
      *  or one of these errors:
      *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
@@ -88,13 +88,13 @@
 
     /**
      * Send a multi-part text based SMS.
-     * 
+     *
      * @param destinationAddress the address to send the message to
      * @param scAddress is the service center address or null to use
      *   the current default SMSC
      * @param parts an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of 
+     * @param sentIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been sent.
      *   The result code will be <code>Activity.RESULT_OK<code> for success,
@@ -102,7 +102,7 @@
      *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
      *   <code>RESULT_ERROR_RADIO_OFF</code>
      *   <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of 
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been delivered
      *   to the recipient.  The raw pdu of the status report is in the
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2b4195b..bab0603 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -21,7 +21,7 @@
 import android.telephony.NeighboringCellInfo;
 
 /**
- * Interface used to interact with the phone.  Mostly this is used by the 
+ * Interface used to interact with the phone.  Mostly this is used by the
  * TelephonyManager class.  A few places are still using this directly.
  * Please clean them up if possible and use TelephonyManager insteadl.
  *
@@ -135,7 +135,7 @@
     /**
      * Cancels the missed calls notification.
      */
-    void cancelMissedCallsNotification(); 
+    void cancelMissedCallsNotification();
 
     /**
      * Supply a pin to unlock the SIM.  Blocks until a result is determined.
@@ -147,7 +147,7 @@
     /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
      * without SEND (so <code>dial</code> is not appropriate).
-     * 
+     *
      * @param dialString the MMI command to be executed.
      * @return true if MMI command is executed.
      */
@@ -213,4 +213,13 @@
      int getCallState();
      int getDataActivity();
      int getDataState();
+
+    /**
+     * Returns the current active phone type as integer.
+     * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
+     * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
+     */
+    int getActivePhoneType();
+
 }
+
diff --git a/telephony/java/com/android/internal/telephony/SimCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
similarity index 70%
rename from telephony/java/com/android/internal/telephony/SimCard.java
rename to telephony/java/com/android/internal/telephony/IccCard.java
index 03b366f..d7ad492 100644
--- a/telephony/java/com/android/internal/telephony/SimCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -22,35 +22,34 @@
 /**
  * {@hide}
  */
-public interface SimCard
-{
-    /* The extra data for broacasting intent INTENT_SIM_STATE_CHANGE */
-    static public final String INTENT_KEY_SIM_STATE = "ss";
-    /* NOT_READY means the SIM interface is not ready (eg, radio is off or powering on) */
-    static public final String INTENT_VALUE_SIM_NOT_READY = "NOT_READY";
-    /* ABSENT means SIM is missing */
-    static public final String INTENT_VALUE_SIM_ABSENT = "ABSENT";
-    /* LOCKED means SIM is locked by pin or by network */
-    static public final String INTENT_VALUE_SIM_LOCKED = "LOCKED";
-    /* READY means SIM is ready to access */
-    static public final String INTENT_VALUE_SIM_READY = "READY";
-    /* IMSI means SIM IMSI is ready in property */
-    static public final String INTENT_VALUE_SIM_IMSI = "IMSI";
-    /* LOADED means all SIM records, including IMSI, are loaded */
-    static public final String INTENT_VALUE_SIM_LOADED = "LOADED";
-    /* The extra data for broacasting intent INTENT_SIM_STATE_CHANGE */
+public interface IccCard {
+    /* The extra data for broacasting intent INTENT_ICC_STATE_CHANGE */
+    static public final String INTENT_KEY_ICC_STATE = "ss";
+    /* NOT_READY means the ICC interface is not ready (eg, radio is off or powering on) */
+    static public final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY";
+    /* ABSENT means ICC is missing */
+    static public final String INTENT_VALUE_ICC_ABSENT = "ABSENT";
+    /* LOCKED means ICC is locked by pin or by network */
+    static public final String INTENT_VALUE_ICC_LOCKED = "LOCKED";
+    /* READY means ICC is ready to access */
+    static public final String INTENT_VALUE_ICC_READY = "READY";
+    /* IMSI means ICC IMSI is ready in property */
+    static public final String INTENT_VALUE_ICC_IMSI = "IMSI";
+    /* LOADED means all ICC records, including IMSI, are loaded */
+    static public final String INTENT_VALUE_ICC_LOADED = "LOADED";
+    /* The extra data for broacasting intent INTENT_ICC_STATE_CHANGE */
     static public final String INTENT_KEY_LOCKED_REASON = "reason";
-    /* PIN means SIM is locked on PIN1 */
+    /* PIN means ICC is locked on PIN1 */
     static public final String INTENT_VALUE_LOCKED_ON_PIN = "PIN";
-    /* PUK means SIM is locked on PUK1 */
+    /* PUK means ICC is locked on PUK1 */
     static public final String INTENT_VALUE_LOCKED_ON_PUK = "PUK";
-    /* NETWORK means SIM is locked on NETWORK PERSONALIZATION */
+    /* NETWORK means ICC is locked on NETWORK PERSONALIZATION */
     static public final String INTENT_VALUE_LOCKED_NETWORK = "NETWORK";
 
 
     /*
-      UNKNOWN is a transient state, for example, after uesr inputs sim pin under
-      PIN_REQUIRED state, the query for sim status returns UNKNOWN before it
+      UNKNOWN is a transient state, for example, after uesr inputs ICC pin under
+      PIN_REQUIRED state, the query for ICC status returns UNKNOWN before it
       turns to READY
      */
     public enum State {
@@ -73,7 +72,7 @@
      * Notifies handler of any transition into State.ABSENT
      */
     void registerForAbsent(Handler h, int what, Object obj);
-    void unregisterForAbsent(Handler h);    
+    void unregisterForAbsent(Handler h);
 
     /**
      * Notifies handler of any transition into State.isPinLocked()
@@ -88,7 +87,7 @@
     void unregisterForNetworkLocked(Handler h);
 
     /**
-     * Supply the SIM PIN to the SIM
+     * Supply the ICC PIN to the ICC
      *
      * When the operation is complete, onComplete will be sent to it's
      * Handler.
@@ -100,11 +99,11 @@
      *
      * If the supplied PIN is incorrect:
      * ((AsyncResult)onComplete.obj).exception != null
-     * && ((AsyncResult)onComplete.obj).exception 
+     * && ((AsyncResult)onComplete.obj).exception
      *       instanceof com.android.internal.telephony.gsm.CommandException)
      * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
      *          .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
-     * 
+     *
      *
      */
 
@@ -114,30 +113,30 @@
     void supplyPuk2 (String puk2, String newPin2, Message onComplete);
 
     /**
-     * Check whether sim pin lock is enabled
+     * Check whether ICC pin lock is enabled
      * This is a sync call which returns the cached pin enabled state
      *
-     * @return true for sim locked enabled
-     *         false for sim locked disabled
+     * @return true for ICC locked enabled
+     *         false for ICC locked disabled
      */
-    boolean getSimLockEnabled ();
+    boolean getIccLockEnabled ();
 
     /**
-     * Set the sim pin lock enabled or disabled
+     * Set the ICC pin lock enabled or disabled
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param enabled "true" for locked "false" for unlocked.
-     * @param password needed to change the sim pin state, aka. Pin1
+     * @param password needed to change the ICC pin state, aka. Pin1
      * @param onComplete
      *        onComplete.obj will be an AsyncResult
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void setSimLockEnabled(boolean enabled, String password, Message onComplete);
+    void setIccLockEnabled(boolean enabled, String password, Message onComplete);
 
 
     /**
-     * Change the sim password used in sim pin lock
+     * Change the ICC password used in ICC pin lock
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param oldPassword is the old password
@@ -147,33 +146,33 @@
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void changeSimLockPassword(String oldPassword, String newPassword,
+    void changeIccLockPassword(String oldPassword, String newPassword,
                            Message onComplete);
 
     /**
-     * Check whether sim fdn (fixed dialing number) is enabled
+     * Check whether ICC fdn (fixed dialing number) is enabled
      * This is a sync call which returns the cached pin enabled state
      *
-     * @return true for sim fdn enabled
-     *         false for sim fdn disabled
+     * @return true for ICC fdn enabled
+     *         false for ICC fdn disabled
      */
-    boolean getSimFdnEnabled ();
+    boolean getIccFdnEnabled ();
 
     /**
-     * Set the sim fdn enabled or disabled
+     * Set the ICC fdn enabled or disabled
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param enabled "true" for locked "false" for unlocked.
-     * @param password needed to change the sim fdn enable, aka Pin2
+     * @param password needed to change the ICC fdn enable, aka Pin2
      * @param onComplete
      *        onComplete.obj will be an AsyncResult
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void setSimFdnEnabled(boolean enabled, String password, Message onComplete);
+    void setIccFdnEnabled(boolean enabled, String password, Message onComplete);
 
     /**
-     * Change the sim password used in sim fdn enable
+     * Change the ICC password used in ICC fdn enable
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param oldPassword is the old password
@@ -183,13 +182,13 @@
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void changeSimFdnPassword(String oldPassword, String newPassword,
+    void changeIccFdnPassword(String oldPassword, String newPassword,
                            Message onComplete);
 
     void supplyNetworkDepersonalization (String pin, Message onComplete);
 
     /**
-     * Returns service provider name stored in SIM card.
+     * Returns service provider name stored in ICC card.
      * If there is no service provider name associated or the record is not
      * yet available, null will be returned <p>
      *
@@ -199,7 +198,7 @@
      *
      * Also available via Android property "gsm.sim.operator.alpha"
      *
-     * @return Service Provider Name stored in SIM card
+     * @return Service Provider Name stored in ICC card
      *         null if no service provider name associated or the record is not
      *         yet available
      *
diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java
new file mode 100644
index 0000000..9f60a6c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccCardApplication.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+
+/**
+ * See also RIL_AppStatus in include/telephony/ril.h
+ *
+ * {@hide}
+ */
+public class IccCardApplication {
+    public enum AppType{
+        APPTYPE_UNKNOWN,
+        APPTYPE_SIM,
+        APPTYPE_USIM,
+        APPTYPE_RUIM,
+        APPTYPE_CSIM
+    };
+
+    public enum AppState{
+        APPSTATE_UNKNOWN,
+        APPSTATE_DETECTED,
+        APPSTATE_PIN,
+        APPSTATE_PUK,
+        APPSTATE_SUBSCRIPTION_PERSO,
+        APPSTATE_READY;
+
+        boolean isPinRequired() {
+            return this == APPSTATE_PIN;
+        }
+
+        boolean isPukRequired() {
+            return this == APPSTATE_PUK;
+        }
+
+        boolean isSubscriptionPersoEnabled() {
+            return this == APPSTATE_SUBSCRIPTION_PERSO;
+        }
+
+        boolean isAppReady() {
+            return this == APPSTATE_READY;
+        }
+
+        boolean isAppNotReady() {
+            return this == APPSTATE_UNKNOWN  ||
+                   this == APPSTATE_DETECTED;
+        }
+    };
+
+    public enum PersoSubState{
+        PERSOSUBSTATE_UNKNOWN,
+        PERSOSUBSTATE_IN_PROGRESS,
+        PERSOSUBSTATE_READY,
+        PERSOSUBSTATE_SIM_NETWORK,
+        PERSOSUBSTATE_SIM_NETWORK_SUBSET,
+        PERSOSUBSTATE_SIM_CORPORATE,
+        PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
+        PERSOSUBSTATE_SIM_SIM,
+        PERSOSUBSTATE_SIM_NETWORK_PUK,
+        PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
+        PERSOSUBSTATE_SIM_CORPORATE_PUK,
+        PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
+        PERSOSUBSTATE_SIM_SIM_PUK,
+        PERSOSUBSTATE_RUIM_NETWORK1,
+        PERSOSUBSTATE_RUIM_NETWORK2,
+        PERSOSUBSTATE_RUIM_HRPD,
+        PERSOSUBSTATE_RUIM_CORPORATE,
+        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
+        PERSOSUBSTATE_RUIM_RUIM,
+        PERSOSUBSTATE_RUIM_NETWORK1_PUK,
+        PERSOSUBSTATE_RUIM_NETWORK2_PUK,
+        PERSOSUBSTATE_RUIM_HRPD_PUK,
+        PERSOSUBSTATE_RUIM_CORPORATE_PUK,
+        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
+        PERSOSUBSTATE_RUIM_RUIM_PUK;
+
+        boolean isPersoSubStateUnknown() {
+            return this == PERSOSUBSTATE_UNKNOWN;
+        }
+    };
+
+    public AppType        app_type;
+    public AppState       app_state;
+    // applicable only if app_state == RIL_APPSTATE_SUBSCRIPTION_PERSO
+    public PersoSubState  perso_substate;
+    // null terminated string, e.g., from 0xA0, 0x00 -> 0x41, 0x30, 0x30, 0x30 */
+    public String         aid;
+    // null terminated string
+    public String         app_label;
+    // applicable to USIM and CSIM
+    public int            pin1_replaced;
+    public int            pin1;
+    public int            pin2;
+
+    AppType AppTypeFromRILInt(int type) {
+        AppType newType;
+        /* RIL_AppType ril.h */
+        switch(type) {
+            case 0: newType = AppType.APPTYPE_UNKNOWN; break;
+            case 1: newType = AppType.APPTYPE_SIM;     break;
+            case 2: newType = AppType.APPTYPE_USIM;    break;
+            case 3: newType = AppType.APPTYPE_RUIM;    break;
+            case 4: newType = AppType.APPTYPE_CSIM;    break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_AppType: " +type);
+        }
+        return newType;
+    }
+
+    AppState AppStateFromRILInt(int state) {
+        AppState newState;
+        /* RIL_AppState ril.h */
+        switch(state) {
+            case 0: newState = AppState.APPSTATE_UNKNOWN;  break;
+            case 1: newState = AppState.APPSTATE_DETECTED; break;
+            case 2: newState = AppState.APPSTATE_PIN; break;
+            case 3: newState = AppState.APPSTATE_PUK; break;
+            case 4: newState = AppState.APPSTATE_SUBSCRIPTION_PERSO; break;
+            case 5: newState = AppState.APPSTATE_READY; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_AppState: " +state);
+        }
+        return newState;
+    }
+
+    PersoSubState PersoSubstateFromRILInt(int substate) {
+        PersoSubState newSubState;
+        /* RIL_PeroSubstate ril.h */
+        switch(substate) {
+            case 0:  newSubState = PersoSubState.PERSOSUBSTATE_UNKNOWN;  break;
+            case 1:  newSubState = PersoSubState.PERSOSUBSTATE_IN_PROGRESS; break;
+            case 2:  newSubState = PersoSubState.PERSOSUBSTATE_READY; break;
+            case 3:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK; break;
+            case 4:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET; break;
+            case 5:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_CORPORATE; break;
+            case 6:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER; break;
+            case 7:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_SIM;  break;
+            case 8:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK_PUK; break;
+            case 9:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK; break;
+            case 10: newSubState = PersoSubState.PERSOSUBSTATE_SIM_CORPORATE_PUK; break;
+            case 11: newSubState = PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK; break;
+            case 12: newSubState = PersoSubState.PERSOSUBSTATE_SIM_SIM_PUK; break;
+            case 13: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1; break;
+            case 14: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2; break;
+            case 15: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_HRPD; break;
+            case 16: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE; break;
+            case 17: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER; break;
+            case 18: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_RUIM; break;
+            case 19: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1_PUK; break;
+            case 20: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2_PUK; break;
+            case 21: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_HRPD_PUK ; break;
+            case 22: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE_PUK; break;
+            case 23: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK; break;
+            case 24: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_RUIM_PUK; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_PersoSubstate: " +substate);
+        }
+        return newSubState;
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/IccCardStatus.java b/telephony/java/com/android/internal/telephony/IccCardStatus.java
new file mode 100644
index 0000000..b602b1c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccCardStatus.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import java.util.ArrayList;
+
+/**
+ * See also RIL_CardStatus in include/telephony/ril.h
+ *
+ * {@hide}
+ */
+public class IccCardStatus {
+    static final int CARD_MAX_APPS = 8;
+
+    public enum CardState {
+        CARDSTATE_ABSENT,
+        CARDSTATE_PRESENT,
+        CARDSTATE_ERROR;
+
+        boolean isCardPresent() {
+            return this == CARDSTATE_PRESENT;
+        }
+    };
+
+    public enum PinState {
+        PINSTATE_UNKNOWN,
+        PINSTATE_ENABLED_NOT_VERIFIED,
+        PINSTATE_ENABLED_VERIFIED,
+        PINSTATE_DISABLED,
+        PINSTATE_ENABLED_BLOCKED,
+        PINSTATE_ENABLED_PERM_BLOCKED
+    };
+
+    public CardState  card_state;
+    public PinState   universal_pin_state;
+    public int        gsm_umts_subscription_app_index;
+    public int        cdma_subscription_app_index;
+    public int        num_applications;
+
+    ArrayList<IccCardApplication> application = new ArrayList<IccCardApplication>(CARD_MAX_APPS);
+
+    CardState CardStateFromRILInt(int state) {
+        CardState newState;
+        /* RIL_CardState ril.h */
+        switch(state) {
+            case 0: newState = CardState.CARDSTATE_ABSENT; break;
+            case 1: newState = CardState.CARDSTATE_PRESENT; break;
+            case 2: newState = CardState.CARDSTATE_ERROR; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_CardState: " +state);
+        }
+        return newState;
+    }
+
+    PinState PinStateFromRILInt(int state) {
+        PinState newState;
+        /* RIL_PinState ril.h */
+        switch(state) {
+            case 0: newState = PinState.PINSTATE_UNKNOWN; break;
+            case 1: newState = PinState.PINSTATE_ENABLED_NOT_VERIFIED; break;
+            case 2: newState = PinState.PINSTATE_ENABLED_VERIFIED; break;
+            case 3: newState = PinState.PINSTATE_DISABLED; break;
+            case 4: newState = PinState.PINSTATE_ENABLED_BLOCKED; break;
+            case 5: newState = PinState.PINSTATE_ENABLED_PERM_BLOCKED; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_PinState: " +state);
+        }
+        return newState;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
new file mode 100644
index 0000000..014fbb6
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * {@hide}
+ */
+public interface IccConstants {
+    // GSM SIM file ids from TS 51.011
+    static final int EF_ADN = 0x6F3A;
+    static final int EF_FDN = 0x6F3B;
+    static final int EF_SDN = 0x6F49;
+    static final int EF_EXT1 = 0x6F4A;
+    static final int EF_EXT2 = 0x6F4B;
+    static final int EF_EXT3 = 0x6F4C;
+    static final int EF_EXT6 = 0x6fc8;   // Ext record for EF[MBDN]
+    static final int EF_MWIS = 0x6FCA;
+    static final int EF_MBDN = 0x6fc7;
+    static final int EF_PNN = 0x6fc5;
+    static final int EF_SPN = 0x6F46;
+    static final int EF_SMS = 0x6F3C;
+    static final int EF_ICCID = 0x2fe2;
+    static final int EF_AD = 0x6FAD;
+    static final int EF_MBI = 0x6fc9;
+    static final int EF_MSISDN = 0x6f40;
+    static final int EF_SPDI = 0x6fcd;
+    static final int EF_SST = 0x6f38;
+    static final int EF_CFIS = 0x6FCB;
+    static final int EF_IMG = 0x4f20;
+
+    // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
+    static final int EF_MAILBOX_CPHS = 0x6F17;
+    static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
+    static final int EF_CFF_CPHS = 0x6F13;
+    static final int EF_SPN_CPHS = 0x6f14;
+    static final int EF_SPN_SHORT_CPHS = 0x6f18;
+    static final int EF_INFO_CPHS = 0x6f16;
+
+    // CDMA RUIM file ids from 3GPP2 C.S0023-0
+    static final int EF_CST = 0x6f32;
+    static final int EF_RUIM_SPN =0x6F41;
+
+    // SMS record length from TS 51.011 10.5.3
+    static public final int SMS_RECORD_LENGTH = 176;
+
+    static final String MF_SIM = "3F00";
+    static final String DF_TELECOM = "7F10";
+    static final String DF_GRAPHICS = "5F50";
+    static final String DF_GSM = "7F20";
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccException.java
similarity index 79%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccException.java
index 72790d0..1659a4e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccException.java
@@ -14,20 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+public class IccException extends Exception {
+    public IccException() {
 
     }
 
-    SimFileTypeMismatch(String s)
-    {
+    public IccException(String s) {
         super(s);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/IccFileHandler.java b/telephony/java/com/android/internal/telephony/IccFileHandler.java
new file mode 100644
index 0000000..92ddd2c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccFileHandler.java
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.*;
+import android.util.Log;
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public abstract class IccFileHandler extends Handler implements IccConstants {
+
+    //from TS 11.11 9.1 or elsewhere
+    static protected final int COMMAND_READ_BINARY = 0xb0;
+    static protected final int COMMAND_UPDATE_BINARY = 0xd6;
+    static protected final int COMMAND_READ_RECORD = 0xb2;
+    static protected final int COMMAND_UPDATE_RECORD = 0xdc;
+    static protected final int COMMAND_SEEK = 0xa2;
+    static protected final int COMMAND_GET_RESPONSE = 0xc0;
+
+    // from TS 11.11 9.2.5
+    static protected final int READ_RECORD_MODE_ABSOLUTE = 4;
+
+    //***** types of files  TS 11.11 9.3
+    static protected final int EF_TYPE_TRANSPARENT = 0;
+    static protected final int EF_TYPE_LINEAR_FIXED = 1;
+    static protected final int EF_TYPE_CYCLIC = 3;
+
+    //***** types of files  TS 11.11 9.3
+    static protected final int TYPE_RFU = 0;
+    static protected final int TYPE_MF  = 1;
+    static protected final int TYPE_DF  = 2;
+    static protected final int TYPE_EF  = 4;
+
+    // size of GET_RESPONSE for EF's
+    static protected final int GET_RESPONSE_EF_SIZE_BYTES = 15;
+    static protected final int GET_RESPONSE_EF_IMG_SIZE_BYTES = 10;
+
+    // Byte order received in response to COMMAND_GET_RESPONSE
+    // Refer TS 51.011 Section 9.2.1
+    static protected final int RESPONSE_DATA_RFU_1 = 0;
+    static protected final int RESPONSE_DATA_RFU_2 = 1;
+
+    static protected final int RESPONSE_DATA_FILE_SIZE_1 = 2;
+    static protected final int RESPONSE_DATA_FILE_SIZE_2 = 3;
+
+    static protected final int RESPONSE_DATA_FILE_ID_1 = 4;
+    static protected final int RESPONSE_DATA_FILE_ID_2 = 5;
+    static protected final int RESPONSE_DATA_FILE_TYPE = 6;
+    static protected final int RESPONSE_DATA_RFU_3 = 7;
+    static protected final int RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
+    static protected final int RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
+    static protected final int RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
+    static protected final int RESPONSE_DATA_FILE_STATUS = 11;
+    static protected final int RESPONSE_DATA_LENGTH = 12;
+    static protected final int RESPONSE_DATA_STRUCTURE = 13;
+    static protected final int RESPONSE_DATA_RECORD_LENGTH = 14;
+
+
+    //***** Events
+
+    /** Finished retrieving size of transparent EF; start loading. */
+    static protected final int EVENT_GET_BINARY_SIZE_DONE = 4;
+    /** Finished loading contents of transparent EF; post result. */
+    static protected final int EVENT_READ_BINARY_DONE = 5;
+    /** Finished retrieving size of records for linear-fixed EF; now load. */
+    static protected final int EVENT_GET_RECORD_SIZE_DONE = 6;
+    /** Finished loading single record from a linear-fixed EF; post result. */
+    static protected final int EVENT_READ_RECORD_DONE = 7;
+    /** Finished retrieving record size; post result. */
+    static protected final int EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE = 8;
+    /** Finished retrieving image instance record; post result. */
+    static protected final int EVENT_READ_IMG_DONE = 9;
+    /** Finished retrieving icon data; post result. */
+    static protected final int EVENT_READ_ICON_DONE = 10;
+
+     // member variables
+    protected PhoneBase phone;
+
+    static class LoadLinearFixedContext {
+
+        int efid;
+        int recordNum, recordSize, countRecords;
+        boolean loadAll;
+
+        Message onLoaded;
+
+        ArrayList<byte[]> results;
+
+        LoadLinearFixedContext(int efid, int recordNum, Message onLoaded) {
+            this.efid = efid;
+            this.recordNum = recordNum;
+            this.onLoaded = onLoaded;
+            this.loadAll = false;
+        }
+
+        LoadLinearFixedContext(int efid, Message onLoaded) {
+            this.efid = efid;
+            this.recordNum = 1;
+            this.loadAll = true;
+            this.onLoaded = onLoaded;
+        }
+    }
+
+    /**
+     * Default constructor
+     */
+    protected IccFileHandler(PhoneBase phone) {
+        super();
+        this.phone = phone;
+    }
+
+    public void dispose() {
+    }
+
+    //***** Public Methods
+
+    /**
+     * Load a record from a SIM Linear Fixed EF
+     *
+     * @param fileid EF id
+     * @param recordNum 1-based (not 0-based) record number
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+    public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) {
+        Message response
+            = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
+                        new LoadLinearFixedContext(fileid, recordNum, onLoaded));
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load a image instance record from a SIM Linear Fixed EF-IMG
+     *
+     * @param recordNum 1-based (not 0-based) record number
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+    public void loadEFImgLinearFixed(int recordNum, Message onLoaded) {
+        Message response = obtainMessage(EVENT_READ_IMG_DONE,
+                new LoadLinearFixedContext(IccConstants.EF_IMG, recordNum,
+                        onLoaded));
+
+        // TODO(): Verify when path changes are done.
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, IccConstants.EF_IMG, "img",
+                recordNum, READ_RECORD_MODE_ABSOLUTE,
+                GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * get record size for a linear fixed EF
+     *
+     * @param fileid EF id
+     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]
+     *        int[0] is the record length int[1] is the total length of the EF
+     *        file int[3] is the number of records in the EF file So int[0] *
+     *        int[3] = int[1]
+     */
+    public void getEFLinearRecordSize(int fileid, Message onLoaded) {
+        Message response
+                = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE,
+                        new LoadLinearFixedContext(fileid, onLoaded));
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+                    0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load all records from a SIM Linear Fixed EF
+     *
+     * @param fileid EF id
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is an ArrayList<byte[]>
+     *
+     */
+    public void loadEFLinearFixedAll(int fileid, Message onLoaded) {
+        Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
+                        new LoadLinearFixedContext(fileid,onLoaded));
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load a SIM Transparent EF
+     *
+     * @param fileid EF id
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+
+    public void loadEFTransparent(int fileid, Message onLoaded) {
+        Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
+                        fileid, 0, onLoaded);
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load a SIM Transparent EF-IMG. Used right after loadEFImgLinearFixed to
+     * retrive STK's icon data.
+     *
+     * @param fileid EF id
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+    public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset,
+            int length, Message onLoaded) {
+        Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
+                onLoaded);
+
+        phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, "img", highOffset, lowOffset,
+                length, null, null, response);
+    }
+
+    /**
+     * Update a record in a linear fixed EF
+     * @param fileid EF id
+     * @param recordNum 1-based (not 0-based) record number
+     * @param data must be exactly as long as the record in the EF
+     * @param pin2 for CHV2 operations, otherwist must be null
+     * @param onComplete onComplete.obj will be an AsyncResult
+     *                   onComplete.obj.userObj will be a IccIoResult on success
+     */
+    public void updateEFLinearFixed(int fileid, int recordNum, byte[] data,
+            String pin2, Message onComplete) {
+        phone.mCM.iccIO(COMMAND_UPDATE_RECORD, fileid, getEFPath(fileid),
+                        recordNum, READ_RECORD_MODE_ABSOLUTE, data.length,
+                        IccUtils.bytesToHexString(data), pin2, onComplete);
+    }
+
+    /**
+     * Update a transparent EF
+     * @param fileid EF id
+     * @param data must be exactly as long as the EF
+     */
+    public void updateEFTransparent(int fileid, byte[] data, Message onComplete) {
+        phone.mCM.iccIO(COMMAND_UPDATE_BINARY, fileid, getEFPath(fileid),
+                        0, 0, data.length,
+                        IccUtils.bytesToHexString(data), null, onComplete);
+    }
+
+
+    //***** Abstract Methods
+
+
+    //***** Private Methods
+
+    private void sendResult(Message response, Object result, Throwable ex) {
+        if (response == null) {
+            return;
+        }
+
+        AsyncResult.forMessage(response, result, ex);
+
+        response.sendToTarget();
+    }
+
+    //***** Overridden from Handler
+
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+        IccIoResult result;
+        Message response = null;
+        String str;
+        LoadLinearFixedContext lc;
+
+        IccException iccException;
+        byte data[];
+        int size;
+        int fileid;
+        int recordNum;
+        int recordSize[];
+
+        try {
+            switch (msg.what) {
+            case EVENT_READ_IMG_DONE:
+                ar = (AsyncResult) msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                iccException = result.getException();
+                if (iccException != null) {
+                    sendResult(response, result.payload, ar.exception);
+                }
+                break;
+            case EVENT_READ_ICON_DONE:
+                ar = (AsyncResult) msg.obj;
+                response = (Message) ar.userObj;
+                result = (IccIoResult) ar.result;
+
+                iccException = result.getException();
+                if (iccException != null) {
+                    sendResult(response, result.payload, ar.exception);
+                }
+                break;
+            case EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE:
+                ar = (AsyncResult)msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                data = result.payload;
+
+                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE] ||
+                    EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                recordSize = new int[3];
+                recordSize[0] = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
+                recordSize[1] = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
+                recordSize[2] = recordSize[1] / recordSize[0];
+
+                sendResult(response, recordSize, null);
+                break;
+             case EVENT_GET_RECORD_SIZE_DONE:
+                ar = (AsyncResult)msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                data = result.payload;
+                fileid = lc.efid;
+                recordNum = lc.recordNum;
+
+                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                lc.recordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
+
+                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
+
+                lc.countRecords = size / lc.recordSize;
+
+                 if (lc.loadAll) {
+                     lc.results = new ArrayList<byte[]>(lc.countRecords);
+                 }
+
+                 phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),
+                         lc.recordNum,
+                         READ_RECORD_MODE_ABSOLUTE,
+                         lc.recordSize, null, null,
+                         obtainMessage(EVENT_READ_RECORD_DONE, lc));
+                 break;
+            case EVENT_GET_BINARY_SIZE_DONE:
+                ar = (AsyncResult)msg.obj;
+                response = (Message) ar.userObj;
+                result = (IccIoResult) ar.result;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                data = result.payload;
+
+                fileid = msg.arg1;
+
+                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
+
+                phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
+                                0, 0, size, null, null,
+                                obtainMessage(EVENT_READ_BINARY_DONE,
+                                              fileid, 0, response));
+            break;
+
+            case EVENT_READ_RECORD_DONE:
+
+                ar = (AsyncResult)msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                if (!lc.loadAll) {
+                    sendResult(response, result.payload, null);
+                } else {
+                    lc.results.add(result.payload);
+
+                    lc.recordNum++;
+
+                    if (lc.recordNum > lc.countRecords) {
+                        sendResult(response, lc.results, null);
+                    } else {
+                        phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),
+                                    lc.recordNum,
+                                    READ_RECORD_MODE_ABSOLUTE,
+                                    lc.recordSize, null, null,
+                                    obtainMessage(EVENT_READ_RECORD_DONE, lc));
+                    }
+                }
+
+            break;
+
+            case EVENT_READ_BINARY_DONE:
+                ar = (AsyncResult)msg.obj;
+                response = (Message) ar.userObj;
+                result = (IccIoResult) ar.result;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                sendResult(response, result.payload, null);
+            break;
+
+        }} catch (Exception exc) {
+            if (response != null) {
+                sendResult(response, null, exc);
+            } else {
+                loge("uncaught exception" + exc);
+            }
+        }
+    }
+
+    /**
+     * Returns the root path of the EF file.
+     * i.e returns MasterFile + DFfile as a string.
+     * Ex: For EF_ADN on a SIM, it will return "3F007F10"
+     * This function handles only EFids that are common to
+     * RUIM, SIM, USIM and other types of Icc cards.
+     *
+     * @param efId
+     * @return root path of the file.
+     */
+    protected String getCommonIccEFPath(int efid) {
+        switch(efid) {
+        case EF_ADN:
+        case EF_FDN:
+        case EF_MSISDN:
+        case EF_SDN:
+        case EF_EXT1:
+        case EF_EXT2:
+        case EF_EXT3:
+            return MF_SIM + DF_TELECOM;
+
+        case EF_ICCID:
+            return MF_SIM;
+        case EF_IMG:
+            return MF_SIM + DF_TELECOM + DF_GRAPHICS;
+        }
+        return null;
+    }
+
+    protected abstract String getEFPath(int efid);
+    protected abstract void logd(String s);
+
+    protected abstract void loge(String s);
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccFileNotFound.java
similarity index 72%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccFileNotFound.java
index 72790d0..915cea6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccFileNotFound.java
@@ -14,20 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+public class IccFileNotFound extends IccException {
+    IccFileNotFound() {
 
     }
 
-    SimFileTypeMismatch(String s)
-    {
+    IccFileNotFound(String s) {
         super(s);
     }
+
+    IccFileNotFound(int ef) {
+        super("ICC EF Not Found 0x" + Integer.toHexString(ef));
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccFileTypeMismatch.java
similarity index 79%
rename from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
rename to telephony/java/com/android/internal/telephony/IccFileTypeMismatch.java
index 72790d0..66fcfa9 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccFileTypeMismatch.java
@@ -14,20 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+public class IccFileTypeMismatch extends IccException {
+    public IccFileTypeMismatch() {
 
     }
 
-    SimFileTypeMismatch(String s)
-    {
+    public IccFileTypeMismatch(String s) {
         super(s);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimIoResult.java b/telephony/java/com/android/internal/telephony/IccIoResult.java
similarity index 67%
rename from telephony/java/com/android/internal/telephony/gsm/SimIoResult.java
rename to telephony/java/com/android/internal/telephony/IccIoResult.java
index 2c4da83..a6e0ec3 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimIoResult.java
+++ b/telephony/java/com/android/internal/telephony/IccIoResult.java
@@ -14,33 +14,30 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
 public class
-SimIoResult
-{
+IccIoResult {
     int sw1;
     int sw2;
-    byte[] payload;
 
-    public SimIoResult(int sw1, int sw2, byte[] payload)
-    {
+    public byte[] payload;
+
+    public IccIoResult(int sw1, int sw2, byte[] payload) {
         this.sw1 = sw1;
         this.sw2 = sw2;
         this.payload = payload;
     }
 
-    public SimIoResult(int sw1, int sw2, String hexString)
-    {
-        this(sw1, sw2, SimUtils.hexStringToBytes(hexString));
+    public IccIoResult(int sw1, int sw2, String hexString) {
+        this(sw1, sw2, IccUtils.hexStringToBytes(hexString));
     }
 
-    public String toString()
-    {
-        return "SimIoResponse sw1:0x" + Integer.toHexString(sw1) + " sw2:0x" 
+    public String toString() {
+        return "IccIoResponse sw1:0x" + Integer.toHexString(sw1) + " sw2:0x"
                 + Integer.toHexString(sw2);
     }
 
@@ -49,27 +46,25 @@
      * See GSM 11.11 Section 9.4
      * (the fun stuff is absent in 51.011)
      */
-    public boolean success()
-    {
+    public boolean success() {
         return sw1 == 0x90 || sw1 == 0x91 || sw1 == 0x9e || sw1 == 0x9f;
     }
 
     /**
      * Returns exception on error or null if success
      */
-    public SimException getException()
-    {
+    public IccException getException() {
         if (success()) return null;
-        
+
         switch (sw1) {
             case 0x94:
                 if (sw2 == 0x08) {
-                    return new SimFileTypeMismatch();
+                    return new IccFileTypeMismatch();
                 } else {
-                    return new SimFileNotFound();
+                    return new IccFileNotFound();
                 }
             default:
-                return new SimException("sw1:" + sw1 + " sw2:" + sw2);
+                return new IccException("sw1:" + sw1 + " sw2:" + sw2);
         }
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
new file mode 100644
index 0000000..0bcaaa6
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.content.pm.PackageManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SimPhoneBookInterfaceManager to provide an inter-process communication to
+ * access ADN-like SIM records.
+ */
+public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
+    protected static final boolean DBG = true;
+
+    protected PhoneBase phone;
+    protected AdnRecordCache adnCache;
+    protected Object mLock = new Object();
+    protected int recordSize[];
+    protected boolean success;
+    protected List<AdnRecord> records;
+
+    protected static final boolean ALLOW_SIM_OP_IN_UI_THREAD = false;
+
+    protected static final int EVENT_GET_SIZE_DONE = 1;
+    protected static final int EVENT_LOAD_DONE = 2;
+    protected static final int EVENT_UPDATE_DONE = 3;
+
+    protected Handler mBaseHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+
+            switch (msg.what) {
+                case EVENT_GET_SIZE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    synchronized (mLock) {
+                        if (ar.exception == null) {
+                            recordSize = (int[])ar.result;
+                            // recordSize[0]  is the record length
+                            // recordSize[1]  is the total length of the EF file
+                            // recordSize[2]  is the number of records in the EF file
+                            logd("GET_RECORD_SIZE Size " + recordSize[0] +
+                                    " total " + recordSize[1] +
+                                    " #record " + recordSize[2]);
+                            mLock.notifyAll();
+                        }
+                    }
+                    break;
+                case EVENT_UPDATE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    synchronized (mLock) {
+                        success = (ar.exception == null);
+                        mLock.notifyAll();
+                    }
+                    break;
+                case EVENT_LOAD_DONE:
+                    ar = (AsyncResult)msg.obj;
+                    synchronized (mLock) {
+                        if (ar.exception == null) {
+                            records = (List<AdnRecord>)
+                                    ((ArrayList<AdnRecord>) ar.result);
+                        } else {
+                            if(DBG) logd("Cannot load ADN records");
+                            if (records != null) {
+                                records.clear();
+                            }
+                        }
+                        mLock.notifyAll();
+                    }
+                    break;
+            }
+        }
+    };
+
+    public IccPhoneBookInterfaceManager(PhoneBase phone) {
+        this.phone = phone;
+    }
+
+    public void dispose() {
+    }
+
+    protected void publish() {
+        //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
+        ServiceManager.addService("simphonebook", this);
+    }
+
+    protected abstract void logd(String msg);
+
+    protected abstract void loge(String msg);
+
+    /**
+     * Replace oldAdn with newAdn in ADN-like record in EF
+     *
+     * getAdnRecordsInEf must be called at least once before this function,
+     * otherwise an error will be returned
+     * throws SecurityException if no WRITE_CONTACTS permission
+     *
+     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
+     * @param oldTag adn tag to be replaced
+     * @param oldPhoneNumber adn number to be replaced
+     *        Set both oldTag and oldPhoneNubmer to "" means to replace an
+     *        empty record, aka, insert new record
+     * @param newTag adn tag to be stored
+     * @param newPhoneNumber adn number ot be stored
+     *        Set both newTag and newPhoneNubmer to "" means to replace the old
+     *        record with empty one, aka, delete old record
+     * @param pin2 required to update EF_FDN, otherwise must be null
+     * @return true for success
+     */
+    public boolean
+    updateAdnRecordsInEfBySearch (int efid,
+            String oldTag, String oldPhoneNumber,
+            String newTag, String newPhoneNumber, String pin2) {
+
+
+        if (phone.getContext().checkCallingOrSelfPermission(
+                android.Manifest.permission.WRITE_CONTACTS)
+            != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Requires android.permission.WRITE_CONTACTS permission");
+        }
+
+
+        if (DBG) logd("updateAdnRecordsInEfBySearch: efid=" + efid +
+                " ("+ oldTag + "," + oldPhoneNumber + ")"+ "==>" +
+                " ("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
+        synchronized(mLock) {
+            checkThread();
+            success = false;
+            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE);
+            AdnRecord oldAdn = new AdnRecord(oldTag, oldPhoneNumber);
+            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
+            adnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to update by search");
+            }
+        }
+        return success;
+    }
+
+    /**
+     * Update an ADN-like EF record by record index
+     *
+     * This is useful for iteration the whole ADN file, such as write the whole
+     * phone book or erase/format the whole phonebook
+     * throws SecurityException if no WRITE_CONTACTS permission
+     *
+     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
+     * @param newTag adn tag to be stored
+     * @param newPhoneNumber adn number to be stored
+     *        Set both newTag and newPhoneNubmer to "" means to replace the old
+     *        record with empty one, aka, delete old record
+     * @param index is 1-based adn record index to be updated
+     * @param pin2 required to update EF_FDN, otherwise must be null
+     * @return true for success
+     */
+    public boolean
+    updateAdnRecordsInEfByIndex(int efid, String newTag,
+            String newPhoneNumber, int index, String pin2) {
+
+        if (phone.getContext().checkCallingOrSelfPermission(
+                android.Manifest.permission.WRITE_CONTACTS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Requires android.permission.WRITE_CONTACTS permission");
+        }
+
+        if (DBG) logd("updateAdnRecordsInEfByIndex: efid=" + efid +
+                " Index=" + index + " ==> " +
+                "("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
+        synchronized(mLock) {
+            checkThread();
+            success = false;
+            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE);
+            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
+            adnCache.updateAdnByIndex(efid, newAdn, index, pin2, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to update by index");
+            }
+        }
+        return success;
+    }
+
+    /**
+     * Get the capacity of records in efid
+     *
+     * @param efid the EF id of a ADN-like ICC
+     * @return  int[3] array
+     *            recordSizes[0]  is the single record length
+     *            recordSizes[1]  is the total length of the EF file
+     *            recordSizes[2]  is the number of records in the EF file
+     */
+    public abstract int[] getAdnRecordsSize(int efid);
+
+    /**
+     * Loads the AdnRecords in efid and returns them as a
+     * List of AdnRecords
+     *
+     * throws SecurityException if no READ_CONTACTS permission
+     *
+     * @param efid the EF id of a ADN-like ICC
+     * @return List of AdnRecord
+     */
+    public List<AdnRecord> getAdnRecordsInEf(int efid) {
+
+        if (phone.getContext().checkCallingOrSelfPermission(
+                android.Manifest.permission.READ_CONTACTS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Requires android.permission.READ_CONTACTS permission");
+        }
+
+        if (DBG) logd("getAdnRecordsInEF: efid=" + efid);
+
+        synchronized(mLock) {
+            checkThread();
+            Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE);
+            adnCache.requestLoadAllAdnLike(efid, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to load from the SIM");
+            }
+        }
+            return records;
+    }
+
+    protected void checkThread() {
+        if (!ALLOW_SIM_OP_IN_UI_THREAD) {
+            // Make sure this isn't the UI thread, since it will block
+            if (mBaseHandler.getLooper().equals(Looper.myLooper())) {
+                loge("query() called on the main UI thread!");
+                throw new IllegalStateException(
+                        "You cannot call query on this provder from the main UI thread.");
+            }
+        }
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManagerProxy.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManagerProxy.java
new file mode 100644
index 0000000..1c0fc52
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManagerProxy.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.content.pm.PackageManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * SimPhoneBookInterfaceManager to provide an inter-process communication to
+ * access ADN-like SIM records.
+ */
+public class IccPhoneBookInterfaceManagerProxy extends IIccPhoneBook.Stub {
+    private IccPhoneBookInterfaceManager mIccPhoneBookInterfaceManager;
+
+    public IccPhoneBookInterfaceManagerProxy(IccPhoneBookInterfaceManager
+            iccPhoneBookInterfaceManager) {
+        mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;
+        if(ServiceManager.getService("simphonebook") == null) {
+            ServiceManager.addService("simphonebook", this);
+        }
+    }
+
+    public void setmIccPhoneBookInterfaceManager(
+            IccPhoneBookInterfaceManager iccPhoneBookInterfaceManager) {
+        this.mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;
+    }
+
+    public boolean
+    updateAdnRecordsInEfBySearch (int efid,
+            String oldTag, String oldPhoneNumber,
+            String newTag, String newPhoneNumber,
+            String pin2) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.updateAdnRecordsInEfBySearch(
+                efid, oldTag, oldPhoneNumber, newTag, newPhoneNumber, pin2);
+    }
+
+    public boolean
+    updateAdnRecordsInEfByIndex(int efid, String newTag,
+            String newPhoneNumber, int index, String pin2) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.updateAdnRecordsInEfByIndex(efid,
+                newTag, newPhoneNumber, index, pin2);
+    }
+
+    public int[] getAdnRecordsSize(int efid) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.getAdnRecordsSize(efid);
+    }
+
+    public List<AdnRecord> getAdnRecordsInEf(int efid) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.getAdnRecordsInEf(efid);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java
similarity index 82%
rename from telephony/java/com/android/internal/telephony/gsm/SimProvider.java
rename to telephony/java/com/android/internal/telephony/IccProvider.java
index cece4ba..4cbd779 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimProvider.java
+++ b/telephony/java/com/android/internal/telephony/IccProvider.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.content.ContentProvider;
 import android.content.UriMatcher;
@@ -31,11 +31,16 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.IIccPhoneBook;
+
+
 /**
  * {@hide}
  */
-public class SimProvider extends ContentProvider {
-    private static final String TAG = "SimProvider";
+public class IccProvider extends ContentProvider {
+    private static final String TAG = "IccProvider";
     private static final boolean DBG = false;
 
 
@@ -56,9 +61,9 @@
                             new UriMatcher(UriMatcher.NO_MATCH);
 
     static {
-        URL_MATCHER.addURI("sim", "adn", ADN);
-        URL_MATCHER.addURI("sim", "fdn", FDN);
-        URL_MATCHER.addURI("sim", "sdn", SDN);
+        URL_MATCHER.addURI("icc", "adn", ADN);
+        URL_MATCHER.addURI("icc", "fdn", FDN);
+        URL_MATCHER.addURI("icc", "sdn", SDN);
     }
 
 
@@ -81,21 +86,21 @@
     public Cursor query(Uri url, String[] projection, String selection,
             String[] selectionArgs, String sort) {
         ArrayList<ArrayList> results;
-        
+
         if (!mSimulator) {
             switch (URL_MATCHER.match(url)) {
                 case ADN:
-                    results = loadFromEf(SimConstants.EF_ADN);
+                    results = loadFromEf(IccConstants.EF_ADN);
                     break;
-    
+
                 case FDN:
-                    results = loadFromEf(SimConstants.EF_FDN);
+                    results = loadFromEf(IccConstants.EF_FDN);
                     break;
-    
+
                 case SDN:
-                    results = loadFromEf(SimConstants.EF_SDN);
+                    results = loadFromEf(IccConstants.EF_SDN);
                     break;
-    
+
                 default:
                     throw new IllegalArgumentException("Unknown URL " + url);
             }
@@ -152,11 +157,11 @@
         int match = URL_MATCHER.match(url);
         switch (match) {
             case ADN:
-                efType = SimConstants.EF_ADN;
+                efType = IccConstants.EF_ADN;
                 break;
 
             case FDN:
-                efType = SimConstants.EF_FDN;
+                efType = IccConstants.EF_FDN;
                 pin2 = initialValues.getAsString("pin2");
                 break;
 
@@ -167,7 +172,7 @@
 
         String tag = initialValues.getAsString("tag");
         String number = initialValues.getAsString("number");
-        boolean success = addSimRecordToEf(efType, tag, number, pin2);
+        boolean success = addIccRecordToEf(efType, tag, number, pin2);
 
         if (!success) {
             return null;
@@ -183,7 +188,7 @@
                 buf.append("fdn/");
                 break;
         }
-        
+
         // TODO: we need to find out the rowId for the newly added record
         buf.append(0);
 
@@ -218,11 +223,11 @@
         int match = URL_MATCHER.match(url);
         switch (match) {
             case ADN:
-                efType = SimConstants.EF_ADN;
+                efType = IccConstants.EF_ADN;
                 break;
 
             case FDN:
-                efType = SimConstants.EF_FDN;
+                efType = IccConstants.EF_FDN;
                 break;
 
             default:
@@ -269,7 +274,7 @@
             return 0;
         }
 
-        boolean success = deleteSimRecordFromEf(efType, tag, number, pin2);
+        boolean success = deleteIccRecordFromEf(efType, tag, number, pin2);
         if (!success) {
             return 0;
         }
@@ -287,11 +292,11 @@
         int match = URL_MATCHER.match(url);
         switch (match) {
             case ADN:
-                efType = SimConstants.EF_ADN;
+                efType = IccConstants.EF_ADN;
                 break;
 
             case FDN:
-                efType = SimConstants.EF_FDN;
+                efType = IccConstants.EF_FDN;
                 pin2 = values.getAsString("pin2");
                 break;
 
@@ -305,7 +310,7 @@
         String newTag = values.getAsString("newTag");
         String newNumber = values.getAsString("newNumber");
 
-        boolean success = updateSimRecordInEf(efType, tag, number,
+        boolean success = updateIccRecordInEf(efType, tag, number,
                 newTag, newNumber, pin2);
 
         if (!success) {
@@ -322,17 +327,16 @@
         if (DBG) log("loadFromEf: efType=" + efType);
 
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                adnRecords = simIpb.getAdnRecordsInEf(efType);
+            if (iccIpb != null) {
+                adnRecords = iccIpb.getAdnRecordsInEf(efType);
             }
         } catch (RemoteException ex) {
             // ignore it
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-
         if (adnRecords != null) {
             // Load the results
 
@@ -351,8 +355,8 @@
     }
 
     private boolean
-    addSimRecordToEf(int efType, String name, String number, String pin2) {
-        if (DBG) log("addSimRecordToEf: efType=" + efType + ", name=" + name +
+    addIccRecordToEf(int efType, String name, String number, String pin2) {
+        if (DBG) log("addIccRecordToEf: efType=" + efType + ", name=" + name +
                 ", number=" + number);
 
         boolean success = false;
@@ -361,11 +365,12 @@
         // updateAdnRecordsInEfBySearch()? In any case, we will leave
         // the UI level logic to fill that prereq if necessary. But
         // hopefully, we can remove this requirement.
+
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                success = simIpb.updateAdnRecordsInEfBySearch(efType, "", "",
+            if (iccIpb != null) {
+                success = iccIpb.updateAdnRecordsInEfBySearch(efType, "", "",
                         name, number, pin2);
             }
         } catch (RemoteException ex) {
@@ -373,23 +378,23 @@
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-        if (DBG) log("addSimRecordToEf: " + success);
+        if (DBG) log("addIccRecordToEf: " + success);
         return success;
     }
 
     private boolean
-    updateSimRecordInEf(int efType, String oldName, String oldNumber,
+    updateIccRecordInEf(int efType, String oldName, String oldNumber,
             String newName, String newNumber,String pin2) {
-        if (DBG) log("updateSimRecordInEf: efType=" + efType +
+        if (DBG) log("updateIccRecordInEf: efType=" + efType +
                 ", oldname=" + oldName + ", oldnumber=" + oldNumber +
                 ", newname=" + newName + ", newnumber=" + newNumber);
         boolean success = false;
 
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                success = simIpb.updateAdnRecordsInEfBySearch(efType,
+            if (iccIpb != null) {
+                success = iccIpb.updateAdnRecordsInEfBySearch(efType,
                         oldName, oldNumber, newName, newNumber, pin2);
             }
         } catch (RemoteException ex) {
@@ -397,34 +402,30 @@
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-
-        if (DBG) log("updateSimRecordInEf: " + success);
+        if (DBG) log("updateIccRecordInEf: " + success);
         return success;
     }
 
 
-    private boolean deleteSimRecordFromEf(int efType,
-                                     String name, String number,
-                                     String pin2) {
-        if (DBG) log("deleteSimRecordFromEf: efType=" + efType +
+    private boolean deleteIccRecordFromEf(int efType, String name, String number, String pin2) {
+        if (DBG) log("deleteIccRecordFromEf: efType=" + efType +
                 ", name=" + name + ", number=" + number + ", pin2=" + pin2);
 
         boolean success = false;
 
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                success = simIpb.updateAdnRecordsInEfBySearch(efType,
-                    name, number, "", "", pin2);
+            if (iccIpb != null) {
+                success = iccIpb.updateAdnRecordsInEfBySearch(efType,
+                        name, number, "", "", pin2);
             }
         } catch (RemoteException ex) {
             // ignore it
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-
-        if (DBG) log("deleteSimRecordFromEf: " + success);
+        if (DBG) log("deleteIccRecordFromEf: " + success);
         return success;
     }
 
@@ -449,7 +450,7 @@
     }
 
     private void log(String msg) {
-        Log.d(TAG, "[SimProvider] " + msg);
+        Log.d(TAG, "[IccProvider] " + msg);
     }
 
 }
diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java
new file mode 100644
index 0000000..114094b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccRecords.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public abstract class IccRecords extends Handler implements IccConstants {
+
+    protected static final boolean DBG = true;
+    //***** Instance Variables
+
+    protected PhoneBase phone;
+    protected RegistrantList recordsLoadedRegistrants = new RegistrantList();
+
+    protected int recordsToLoad;  // number of pending load requests
+
+    protected AdnRecordCache adnCache;
+
+    //***** Cached SIM State; cleared on channel close
+
+    protected boolean recordsRequested = false; // true if we've made requests for the sim records
+
+    public String iccid;
+    protected String msisdn = null;  // My mobile number
+    protected String msisdnTag = null;
+    protected String voiceMailNum = null;
+    protected String voiceMailTag = null;
+    protected String newVoiceMailNum = null;
+    protected String newVoiceMailTag = null;
+    protected boolean isVoiceMailFixed = false;
+    protected int countVoiceMessages = 0;
+
+    protected int mncLength = 0;   // 0 is used to indicate that the value
+                         // is not initialized
+    protected int mailboxIndex = 0; // 0 is no mailbox dailing number associated
+
+    protected String spn;
+    protected int spnDisplayCondition;
+
+    //***** Constants
+
+    // Bitmasks for SPN display rules.
+    protected static final int SPN_RULE_SHOW_SPN  = 0x01;
+    protected static final int SPN_RULE_SHOW_PLMN = 0x02;
+
+    //***** Event Constants
+    protected static final int EVENT_SET_MSISDN_DONE = 30;
+
+    //***** Constructor
+
+    public IccRecords(PhoneBase p) {
+        this.phone = p;
+    }
+
+    protected abstract void onRadioOffOrNotAvailable();
+
+    //***** Public Methods
+    public AdnRecordCache getAdnCache() {
+        return adnCache;
+    }
+
+    public void registerForRecordsLoaded(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        recordsLoadedRegistrants.add(r);
+
+        if (recordsToLoad == 0 && recordsRequested == true) {
+            r.notifyRegistrant(new AsyncResult(null, null, null));
+        }
+    }
+
+    public void unregisterForRecordsLoaded(Handler h) {
+        recordsLoadedRegistrants.remove(h);
+    }
+
+    public String getMsisdnNumber() {
+        return msisdn;
+    }
+
+    /**
+     * Set subscriber number to SIM record
+     *
+     * The subscriber number is stored in EF_MSISDN (TS 51.011)
+     *
+     * When the operation is complete, onComplete will be sent to its handler
+     *
+     * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters)
+     * @param number dailing nubmer (up to 20 digits)
+     *        if the number starts with '+', then set to international TOA
+     * @param onComplete
+     *        onComplete.obj will be an AsyncResult
+     *        ((AsyncResult)onComplete.obj).exception == null on success
+     *        ((AsyncResult)onComplete.obj).exception != null on fail
+     */
+    public void setMsisdnNumber(String alphaTag, String number,
+            Message onComplete) {
+
+        msisdn = number;
+        msisdnTag = alphaTag;
+
+        if(DBG) log("Set MSISDN: " + msisdnTag +" " + msisdn);
+
+
+        AdnRecord adn = new AdnRecord(msisdnTag, msisdn);
+
+        new AdnRecordLoader(phone).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null,
+                obtainMessage(EVENT_SET_MSISDN_DONE, onComplete));
+    }
+
+    public String getMsisdnAlphaTag() {
+        return msisdnTag;
+    }
+
+    public String getVoiceMailNumber() {
+        return voiceMailNum;
+    }
+
+    /**
+     * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41)
+     * @return null if SIM is not yet ready or no RUIM entry
+     */
+    public String getServiceProviderName() {
+        return spn;
+    }
+
+    /**
+     * Set voice mail number to SIM record
+     *
+     * The voice mail number can be stored either in EF_MBDN (TS 51.011) or
+     * EF_MAILBOX_CPHS (CPHS 4.2)
+     *
+     * If EF_MBDN is available, store the voice mail number to EF_MBDN
+     *
+     * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS
+     *
+     * So the voice mail number will be stored in both EFs if both are available
+     *
+     * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail.
+     *
+     * When the operation is complete, onComplete will be sent to its handler
+     *
+     * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters)
+     * @param voiceNumber dailing nubmer (upto 20 digits)
+     *        if the number is start with '+', then set to international TOA
+     * @param onComplete
+     *        onComplete.obj will be an AsyncResult
+     *        ((AsyncResult)onComplete.obj).exception == null on success
+     *        ((AsyncResult)onComplete.obj).exception != null on fail
+     */
+    public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber,
+            Message onComplete);
+
+    public String getVoiceMailAlphaTag() {
+        return voiceMailTag;
+    }
+
+    /**
+     * Sets the SIM voice message waiting indicator records
+     * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
+     * @param countWaiting The number of messages waiting, if known. Use
+     *                     -1 to indicate that an unknown number of
+     *                      messages are waiting
+     */
+    public abstract void setVoiceMessageWaiting(int line, int countWaiting);
+
+    /** @return  true if there are messages waiting, false otherwise. */
+    public boolean getVoiceMessageWaiting() {
+        return countVoiceMessages != 0;
+    }
+
+    /**
+     * Returns number of voice messages waiting, if available
+     * If not available (eg, on an older CPHS SIM) -1 is returned if
+     * getVoiceMessageWaiting() is true
+     */
+    public int getCountVoiceMessages() {
+        return countVoiceMessages;
+    }
+
+    /**
+     * Called by STK Service when REFRESH is received.
+     * @param fileChanged indicates whether any files changed
+     * @param fileList if non-null, a list of EF files that changed
+     */
+    public abstract void onRefresh(boolean fileChanged, int[] fileList);
+
+
+    public boolean getRecordsLoaded() {
+        if (recordsToLoad == 0 && recordsRequested == true) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    //***** Overridden from Handler
+    public abstract void handleMessage(Message msg);
+
+    protected abstract void onRecordLoaded();
+
+    protected abstract void onAllRecordsLoaded();
+
+    /**
+     * Returns the SpnDisplayRule based on settings on the SIM and the
+     * specified plmn (currently-registered PLMN).  See TS 22.101 Annex A
+     * and TS 51.011 10.3.11 for details.
+     *
+     * If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
+     */
+    protected abstract int getDisplayRule(String plmn);
+
+    protected abstract void log(String s);
+}
+
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
new file mode 100644
index 0000000..620f2de
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
+
+/**
+ * IccSmsInterfaceManager to provide an inter-process communication to
+ * access Sms in Icc.
+ */
+public abstract class IccSmsInterfaceManager extends ISms.Stub {
+    static final boolean DBG = true;
+
+    protected PhoneBase mPhone;
+    protected Context mContext;
+    protected SMSDispatcher mDispatcher;
+
+    protected IccSmsInterfaceManager(PhoneBase phone){
+        mPhone = phone;
+        mContext = phone.getContext();
+    }
+
+    protected void enforceReceiveAndSend(String message) {
+        mContext.enforceCallingPermission(
+                "android.permission.RECEIVE_SMS", message);
+        mContext.enforceCallingPermission(
+                "android.permission.SEND_SMS", message);
+    }
+
+    /**
+     * Send a Raw PDU SMS
+     *
+     * @param smsc the SMSC to send the message through, or NULL for the
+     *  defatult SMSC
+     * @param pdu the raw PDU to send
+     * @param sentIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     * @param deliveryIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        Context context = mPhone.getContext();
+
+        context.enforceCallingPermission(
+                "android.permission.SEND_SMS",
+                "Sending SMS message");
+        if (DBG) log("sendRawPdu: smsc=" + smsc +
+                " pdu="+ pdu + " sentIntent" + sentIntent +
+                " deliveryIntent" + deliveryIntent);
+        mDispatcher.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+    }
+
+    /**
+     * Send a multi-part text based SMS.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     */
+    public void sendMultipartText(String destinationAddress, String scAddress, List<String> parts,
+            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
+        Context context = mPhone.getContext();
+
+        context.enforceCallingPermission(
+                "android.permission.SEND_SMS",
+                "Sending SMS message");
+        if (DBG) log("sendMultipartText");
+        mDispatcher.sendMultipartText(destinationAddress, scAddress, (ArrayList<String>) parts,
+                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
+    }
+
+    /**
+     * create SmsRawData lists from all sms record byte[]
+     * Use null to indicate "free" record
+     *
+     * @param messages List of message records from EF_SMS.
+     * @return SmsRawData list of all in-used records
+     */
+    protected ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) {
+        int count = messages.size();
+        ArrayList<SmsRawData> ret;
+
+        ret = new ArrayList<SmsRawData>(count);
+
+        for (int i = 0; i < count; i++) {
+            byte[] ba = messages.get(i);
+            if (ba[0] == STATUS_ON_ICC_FREE) {
+                ret.add(null);
+            } else {
+                ret.add(new SmsRawData(messages.get(i)));
+            }
+        }
+
+        return ret;
+    }
+
+    /**
+     * Generates an EF_SMS record from status and raw PDU.
+     *
+     * @param status Message status.  See TS 51.011 10.5.3.
+     * @param pdu Raw message PDU.
+     * @return byte array for the record.
+     */
+    protected byte[] makeSmsRecordData(int status, byte[] pdu) {
+        byte[] data = new byte[IccConstants.SMS_RECORD_LENGTH];
+
+        // Status bits for this record.  See TS 51.011 10.5.3
+        data[0] = (byte)(status & 7);
+
+        System.arraycopy(pdu, 0, data, 1, pdu.length);
+
+        // Pad out with 0xFF's.
+        for (int j = pdu.length+1; j < IccConstants.SMS_RECORD_LENGTH; j++) {
+            data[j] = -1;
+        }
+
+        return data;
+    }
+
+    protected abstract void log(String msg);
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
new file mode 100644
index 0000000..a51d074
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+import android.os.ServiceManager;
+
+import java.util.List;
+
+public class IccSmsInterfaceManagerProxy extends ISms.Stub {
+    private IccSmsInterfaceManager mIccSmsInterfaceManager;
+
+    public IccSmsInterfaceManagerProxy(IccSmsInterfaceManager
+            iccSmsInterfaceManager) {
+        this.mIccSmsInterfaceManager = iccSmsInterfaceManager;
+        if(ServiceManager.getService("isms") == null) {
+            ServiceManager.addService("isms", this);
+        }
+    }
+
+    public void setmIccSmsInterfaceManager(IccSmsInterfaceManager iccSmsInterfaceManager) {
+        this.mIccSmsInterfaceManager = iccSmsInterfaceManager;
+    }
+
+    public boolean
+    updateMessageOnIccEf(int index, int status, byte[] pdu) throws android.os.RemoteException {
+         return mIccSmsInterfaceManager.updateMessageOnIccEf(index, status, pdu);
+    }
+
+    public boolean copyMessageToIccEf(int status, byte[] pdu,
+            byte[] smsc) throws android.os.RemoteException {
+        return mIccSmsInterfaceManager.copyMessageToIccEf(status, pdu, smsc);
+    }
+
+    public List<SmsRawData> getAllMessagesFromIccEf() throws android.os.RemoteException {
+        return mIccSmsInterfaceManager.getAllMessagesFromIccEf();
+    }
+
+    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) throws android.os.RemoteException {
+        mIccSmsInterfaceManager.sendRawPdu(smsc, pdu, sentIntent,
+                deliveryIntent);
+    }
+
+    public void sendMultipartText(String destinationAddress, String scAddress,
+            List<String> parts, List<PendingIntent> sentIntents,
+            List<PendingIntent> deliveryIntents) throws android.os.RemoteException {
+        mIccSmsInterfaceManager.sendMultipartText(destinationAddress, scAddress,
+                parts, sentIntents, deliveryIntents);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
similarity index 90%
rename from telephony/java/com/android/internal/telephony/gsm/SimUtils.java
rename to telephony/java/com/android/internal/telephony/IccUtils.java
index 2eecdba..881ed2d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimUtils.java
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -14,48 +14,48 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-
-import java.io.UnsupportedEncodingException;
+package com.android.internal.telephony;
 
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.util.Log;
 
+import com.android.internal.telephony.GsmAlphabet;
+
+import java.io.UnsupportedEncodingException;
+
 /**
  * Various methods, useful for dealing with SIM data.
  */
-public class SimUtils
-{
-    static final String LOG_TAG="GSM";
+public class IccUtils {
+    static final String LOG_TAG="IccUtils";
 
     /**
      * Many fields in GSM SIM's are stored as nibble-swizzled BCD
      *
-     * Assumes left-justified field that may be padded right with 0xf 
+     * Assumes left-justified field that may be padded right with 0xf
      * values.
      *
      * Stops on invalid BCD value, returning string so far
      */
     public static String
-    bcdToString(byte[] data, int offset, int length)
-    {
+    bcdToString(byte[] data, int offset, int length) {
         StringBuilder ret = new StringBuilder(length*2);
- 
+
         for (int i = offset ; i < offset + length ; i++) {
             byte b;
             int v;
-                        
+
             v = data[i] & 0xf;
             if (v > 9)  break;
             ret.append((char)('0' + v));
 
             v = (data[i] >> 4) & 0xf;
             if (v > 9)  break;
-            ret.append((char)('0' + v));        
+            ret.append((char)('0' + v));
         }
-        
-        return ret.toString();    
+
+        return ret.toString();
     }
 
 
@@ -66,7 +66,7 @@
      * significant nibble.
      *
      * Out-of-range digits are treated as 0 for the sake of the time stamp,
-     * because of this: 
+     * because of this:
      *
      * TS 23.040 section 9.2.3.11
      * "if the MS receives a non-integer value in the SCTS, it shall
@@ -74,13 +74,12 @@
      * exactly as received"
      */
     public static int
-    bcdByteToInt(byte b)
-    {
+    bcdByteToInt(byte b) {
         int ret = 0;
 
         // treat out-of-range BCD values as 0
         if ((b & 0xf0) <= 0x90) {
-            ret = (b >> 4) & 0xf; 
+            ret = (b >> 4) & 0xf;
         }
 
         if ((b & 0x0f) <= 0x09) {
@@ -90,6 +89,24 @@
         return ret;
     }
 
+    /** Decodes BCD byte like {@link bcdByteToInt}, but the most significant BCD
+     *  digit is expected in the most significant nibble.
+     */
+    public static int
+    beBcdByteToInt(byte b) {
+        int ret = 0;
+
+        // treat out-of-range BCD values as 0
+        if ((b & 0xf0) <= 0x90) {
+            ret = ((b >> 4) & 0xf) * 10;
+        }
+
+        if ((b & 0x0f) <= 0x09) {
+            ret +=  (b & 0xf);
+        }
+
+        return ret;
+    }
 
     /**
      * Decodes a string field that's formatted like the EF[ADN] alpha
@@ -97,11 +114,11 @@
      *
      * From TS 51.011 10.5.1:
      *   Coding:
-     *   	this alpha tagging shall use either
-     *      -	the SMS default 7 bit coded alphabet as defined in 
-     *          TS 23.038 [12] with bit 8 set to 0. The alpha identifier 
+     *       this alpha tagging shall use either
+     *      -    the SMS default 7 bit coded alphabet as defined in
+     *          TS 23.038 [12] with bit 8 set to 0. The alpha identifier
      *          shall be left justified. Unused bytes shall be set to 'FF'; or
-     *      -	one of the UCS2 coded options as defined in annex B.
+     *      -    one of the UCS2 coded options as defined in annex B.
      *
      * Annex B from TS 11.11 V8.13.0:
      *      1)  If the first octet in the alpha string is '80', then the
@@ -109,7 +126,7 @@
      *      2)  if the first octet in the alpha string is '81', then the
      *          second octet contains a value indicating the number of
      *          characters in the string, and the third octet contains an
-     *          8 bit number which defines bits 15 to 8 of a 16 bit 
+     *          8 bit number which defines bits 15 to 8 of a 16 bit
      *          base pointer, where bit 16 is set to zero and bits 7 to 1
      *          are also set to zero.  These sixteen bits constitute a
      *          base pointer to a "half page" in the UCS2 code space, to be
@@ -127,8 +144,7 @@
      *          base pointer to a "half page" in the UCS2 code space...
      */
     public static String
-    adnStringFieldToString(byte[] data, int offset, int length)
-    {
+    adnStringFieldToString(byte[] data, int offset, int length) {
         if (length >= 1) {
             if (data[offset] == (byte) 0x80) {
                 int ucslen = (length - 1) / 2;
@@ -208,8 +224,7 @@
     }
 
     static int
-    hexCharToInt(char c)
-    {
+    hexCharToInt(char c) {
         if (c >= '0' && c <= '9') return (c - '0');
         if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
         if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
@@ -219,17 +234,16 @@
 
     /**
      * Converts a hex String to a byte array.
-     * 
+     *
      * @param s A string of hexadecimal characters, must be an even number of
      *          chars long
      *
      * @return byte array representation
-     * 
+     *
      * @throws RuntimeException on invalid format
      */
     public static byte[]
-    hexStringToBytes(String s)
-    {
+    hexStringToBytes(String s) {
         byte[] ret;
 
         if (s == null) return null;
@@ -239,10 +253,10 @@
         ret = new byte[sz/2];
 
         for (int i=0 ; i <sz ; i+=2) {
-            ret[i/2] = (byte) ((hexCharToInt(s.charAt(i)) << 4) 
+            ret[i/2] = (byte) ((hexCharToInt(s.charAt(i)) << 4)
                                 | hexCharToInt(s.charAt(i+1)));
         }
-        
+
         return ret;
     }
 
@@ -253,10 +267,9 @@
      * null returns null
      */
     public static String
-    bytesToHexString(byte[] bytes)
-    {
+    bytesToHexString(byte[] bytes) {
         if (bytes == null) return null;
-        
+
         StringBuilder ret = new StringBuilder(2*bytes.length);
 
         for (int i = 0 ; i < bytes.length ; i++) {
@@ -281,10 +294,9 @@
      * empty string returned on decode error
      */
     public static String
-    networkNameToString(byte[] data, int offset, int length)
-    {
+    networkNameToString(byte[] data, int offset, int length) {
         String ret;
-        
+
         if ((data[offset] & 0x80) != 0x80 || length < 1) {
             return "";
         }
@@ -295,13 +307,12 @@
                 int countSeptets;
                 int unusedBits = data[offset] & 7;
                 countSeptets = (((length - 1) * 8) - unusedBits) / 7 ;
-                ret =  GsmAlphabet.gsm7BitPackedToString(
-                                data, offset + 1, countSeptets);
+                ret =  GsmAlphabet.gsm7BitPackedToString(data, offset + 1, countSeptets);
             break;
             case 1:
                 // UCS2
                 try {
-                    ret = new String(data, 
+                    ret = new String(data,
                             offset + 1, length - 1, "utf-16");
                 } catch (UnsupportedEncodingException ex) {
                     ret = "";
@@ -332,7 +343,7 @@
      * @param data The raw data
      * @param length The length of image body
      * @return The bitmap
-     */    
+     */
     public static Bitmap parseToBnW(byte[] data, int length){
         int valueIndex = 0;
         int width = data[valueIndex++] & 0xFF;
@@ -369,7 +380,7 @@
 
     /**
      * a TS 131.102 image instance of code scheme '11' into color Bitmap
-     * 
+     *
      * @param data The raw data
      * @param length the length of image body
      * @param transparency with or without transparency
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccVmFixedException.java
similarity index 72%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccVmFixedException.java
index 72790d0..45679c1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccVmFixedException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -14,20 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
+public final class IccVmFixedException extends IccException {
+    IccVmFixedException()
     {
 
     }
 
-    SimFileTypeMismatch(String s)
+    public IccVmFixedException(String s)
     {
         super(s);
-    }
-}
+    }    
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccVmNotSupportedException.java
similarity index 70%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccVmNotSupportedException.java
index 72790d0..7e90d24 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccVmNotSupportedException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -14,20 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
+public final class IccVmNotSupportedException extends IccException {
+    IccVmNotSupportedException()
     {
 
     }
 
-    SimFileTypeMismatch(String s)
+    public IccVmNotSupportedException(String s)
     {
         super(s);
-    }
+    }    
 }
diff --git a/telephony/java/com/android/internal/telephony/MmiCode.java b/telephony/java/com/android/internal/telephony/MmiCode.java
index 925b06f..c71ff77 100644
--- a/telephony/java/com/android/internal/telephony/MmiCode.java
+++ b/telephony/java/com/android/internal/telephony/MmiCode.java
@@ -41,14 +41,14 @@
      * @return Localized message for UI display, valid only in COMPLETE
      * or FAILED states. null otherwise
      */
-     
+
     public CharSequence getMessage();
 
     /**
      * Cancels pending MMI request.
      * State becomes CANCELLED unless already COMPLETE or FAILED
      */
-    public void cancel();    
+    public void cancel();
 
     /**
      * @return true if the network response is a REQUEST for more user input.
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 05e61f2..3f210ca 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -17,10 +17,14 @@
 package com.android.internal.telephony;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.Handler;
 import android.os.Message;
+import android.preference.PreferenceManager;
 import android.telephony.CellLocation;
 import android.telephony.ServiceState;
+
+import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.gsm.NetworkInfo;
 import com.android.internal.telephony.gsm.PdpConnection;
 import com.android.internal.telephony.test.SimulatedRadioControl;
@@ -38,13 +42,13 @@
 
     /** used to enable additional debug messages */
     static final boolean DEBUG_PHONE = true;
-    
 
-    /** 
+
+    /**
      * The phone state. One of the following:<p>
      * <ul>
      * <li>IDLE = no phone activity</li>
-     * <li>RINGING = a phone call is ringing or call waiting. 
+     * <li>RINGING = a phone call is ringing or call waiting.
      *  In the latter case, another call is active as well</li>
      * <li>OFFHOOK = The phone is off hook. At least one call
      * exists that is dialing, active or holding and no calls are
@@ -70,7 +74,7 @@
         CONNECTED, CONNECTING, DISCONNECTED, SUSPENDED;
     };
 
-    enum DataActivityState {
+    public enum DataActivityState {
         /**
          * The state of a data activity.
          * <ul>
@@ -109,9 +113,12 @@
     static final String APN_TYPE_DEFAULT = "default";
     /** APN type for MMS traffic */
     static final String APN_TYPE_MMS = "mms";
+    /** APN type for SUPL assisted GPS */
+    static final String APN_TYPE_SUPL = "supl";
 
     // "Features" accessible through the connectivity manager
     static final String FEATURE_ENABLE_MMS = "enableMMS";
+    static final String FEATURE_ENABLE_SUPL = "enableSUPL";
 
     /**
      * Return codes for <code>enableApnType()</code>
@@ -131,6 +138,8 @@
     static final String REASON_DATA_ENABLED = "dataEnabled";
     static final String REASON_GPRS_ATTACHED = "gprsAttached";
     static final String REASON_GPRS_DETACHED = "gprsDetached";
+    static final String REASON_CDMA_DATA_ATTACHED = "cdmaDataAttached";
+    static final String REASON_CDMA_DATA_DETACHED = "cdmaDataDetached";
     static final String REASON_APN_CHANGED = "apnChanged";
     static final String REASON_APN_SWITCHED = "apnSwitched";
     static final String REASON_RESTORE_DEFAULT_APN = "restoreDefaultApn";
@@ -152,12 +161,32 @@
     static final int BM_BOUNDARY    = 6; // upper band boundary
 
     // Used for preferred network type
-    static final int NT_AUTO_TYPE  = 0;  //   WCDMA preferred (auto mode)
-    static final int NT_GSM_TYPE   = 1;  //   GSM only
-    static final int NT_WCDMA_TYPE = 2;  //   WCDMA only
+    // Note NT_* substitute RILConstants.NETWORK_MODE_* above the Phone
+    int NT_MODE_WCDMA_PREF   = 0; /* GSM/WCDMA (WCDMA preferred) */
+    int NT_MODE_GSM_ONLY     = 1; /* GSM only */
+    int NT_MODE_WCDMA_ONLY   = 2; /* WCDMA only */
+    int NT_MODE_GSM_UMTS     = 3; /* GSM/WCDMA (auto mode, according to PRL)
+                                     AVAILABLE Application Settings menu*/
+    int NT_MODE_CDMA         = 4; /* CDMA and EvDo (auto mode, according to PRL)
+                                     AVAILABLE Application Settings menu*/
+    int NT_MODE_CDMA_NO_EVDO = 5; /* CDMA only */
+    int NT_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
+    int NT_MODE_GLOBAL       = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
+                                     AVAILABLE Application Settings menu*/
+    int PREFERRED_NT_MODE    = NT_MODE_GSM_ONLY;
+
+
+    // Used for CDMA roaming mode
+    static final int CDMA_RM_HOME        = 0;  //Home Networks only, as defined in PRL
+    static final int CDMA_RM_AFFILIATED = 1;  //Roaming an Affiliated networks, as defined in PRL
+    static final int CDMA_RM_ANY        = 2;  //Roaming on Any Network, as defined in PRL
+
+    // Used for CDMA subscription mode
+    static final int CDMA_SUBSCRIPTION_RUIM_SIM    = 0; //RUIM/SIM (default)
+    static final int CDMA_SUBSCRIPTION_NV        = 1; //NV -> non-volatile memory
 
     /**
-     * Get the current ServiceState. Use 
+     * Get the current ServiceState. Use
      * <code>registerForServiceStateChanged</code> to be informed of
      * updates.
      */
@@ -167,11 +196,12 @@
      * Get the current CellLocation.
      */
     CellLocation getCellLocation();
-    
+
     /**
      * Get the current DataState. No change notification exists at this
-     * interface -- use 
-     * {@link com.android.internal.telephony.PhoneStateIntentReceiver PhoneStateIntentReceiver} instead.
+     * interface -- use
+     * {@link com.android.internal.telephony.PhoneStateIntentReceiver PhoneStateIntentReceiver}
+     * instead.
      */
     DataState getDataConnectionState();
 
@@ -181,58 +211,70 @@
      * {@link TelephonyManager} instead.
      */
     DataActivityState getDataActivityState();
-    
+
     /**
      * Gets the context for the phone, as set at initialization time.
      */
     Context getContext();
 
-    /** 
+    /**
+     * Disables the DNS check (i.e., allows "0.0.0.0").
+     * Useful for lab testing environment.
+     * @param b true disables the check, false enables.
+     */
+    void disableDnsCheck(boolean b);
+
+    /**
+     * Returns true if the DNS check is currently disabled.
+     */
+    boolean isDnsCheckDisabled();
+
+    /**
      * Get current coarse-grained voice call state.
-     * Use {@link #registerForPhoneStateChanged(Handler, int, Object) 
+     * Use {@link #registerForPhoneStateChanged(Handler, int, Object)
      * registerForPhoneStateChanged()} for change notification. <p>
      * If the phone has an active call and call waiting occurs,
      * then the phone state is RINGING not OFFHOOK
-     * <strong>Note:</strong> 
+     * <strong>Note:</strong>
      * This registration point provides notification of finer-grained
      * changes.<p>
      *
      */
     State getState();
 
-    /** 
+    /**
      * Returns a string identifier for this phone interface for parties
      *  outside the phone app process.
      *  @return The string name.
      */
     String getPhoneName();
 
-    /** 
+    /**
      * Returns an array of string identifiers for the APN types serviced by the
      * currently active or last connected APN.
      *  @return The string array.
      */
     String[] getActiveApnTypes();
-    
-    /** 
+
+    /**
      * Returns a string identifier for currently active or last connected APN.
      *  @return The string name.
      */
     String getActiveApn();
-    
-    /** 
+
+    /**
      * Get current signal strength. No change notification available on this
      * interface. Use <code>PhoneStateNotifier</code> or an equivalent.
-     * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu). 
+     * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu).
      * The following special values are defined:</p>
      * <ul><li>0 means "-113 dBm or less".</li>
      * <li>31 means "-51 dBm or greater".</li></ul>
-     * 
+     *
      * @return Current signal strength in ASU's.
      */
     int getSignalStrengthASU();
-    
-    /** 
+
+    /**
      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
      * This is likely due to some other entity (eg, SIM card application) initiating a call.
      */
@@ -243,7 +285,7 @@
      */
     void unregisterForUnknownConnection(Handler h);
 
-    /** 
+    /**
      * Notifies when any aspect of the voice call state changes.
      * Resulting events will have an AsyncResult in <code>Message.obj</code>.
      * AsyncResult.userData will be set to the obj argument here.
@@ -252,13 +294,13 @@
     void registerForPhoneStateChanged(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for voice call state change notifications. 
+     * Unregisters for voice call state change notifications.
      * Extraneous calls are tolerated silently.
      */
     void unregisterForPhoneStateChanged(Handler h);
 
 
-    /** 
+    /**
      * Notifies when a new ringing or waiting connection has appeared.<p>
      *
      *  Messages received from this:
@@ -267,19 +309,19 @@
      *  AsyncResult.result = a Connection. <p>
      *  Please check Connection.isRinging() to make sure the Connection
      *  has not dropped since this message was posted.
-     *  If Connection.isRinging() is true, then 
+     *  If Connection.isRinging() is true, then
      *   Connection.getCall() == Phone.getRingingCall()
      */
     void registerForNewRingingConnection(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for new ringing connection notification. 
+     * Unregisters for new ringing connection notification.
      * Extraneous calls are tolerated silently
      */
 
     void unregisterForNewRingingConnection(Handler h);
 
-    /** 
+    /**
      * Notifies when an incoming call rings.<p>
      *
      *  Messages received from this:
@@ -288,29 +330,29 @@
      *  AsyncResult.result = a Connection. <p>
      */
     void registerForIncomingRing(Handler h, int what, Object obj);
-    
+
     /**
-     * Unregisters for ring notification. 
+     * Unregisters for ring notification.
      * Extraneous calls are tolerated silently
      */
-    
+
     void unregisterForIncomingRing(Handler h);
-    
-    
-    /** 
+
+
+    /**
      * Notifies when a voice connection has disconnected, either due to local
      * or remote hangup or error.
-     * 
+     *
      *  Messages received from this will have the following members:<p>
      *  <ul><li>Message.obj will be an AsyncResult</li>
      *  <li>AsyncResult.userObj = obj</li>
-     *  <li>AsyncResult.result = a Connection object that is 
+     *  <li>AsyncResult.result = a Connection object that is
      *  no longer connected.</li></ul>
      */
     void registerForDisconnect(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for voice disconnection notification. 
+     * Unregisters for voice disconnection notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForDisconnect(Handler h);
@@ -330,7 +372,7 @@
     void registerForMmiInitiate(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for new MMI initiate notification. 
+     * Unregisters for new MMI initiate notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForMmiInitiate(Handler h);
@@ -346,7 +388,7 @@
     void registerForMmiComplete(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for MMI complete notification. 
+     * Unregisters for MMI complete notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForMmiComplete(Handler h);
@@ -355,7 +397,7 @@
      * Returns a list of MMI codes that are pending. (They have initiated
      * but have not yet completed).
      * Presently there is only ever one.
-     * Use <code>registerForMmiInitiate</code> 
+     * Use <code>registerForMmiInitiate</code>
      * and <code>registerForMmiComplete</code> for change notification.
      */
     public List<? extends MmiCode> getPendingMmiCodes();
@@ -370,14 +412,14 @@
     public void sendUssdResponse(String ussdMessge);
 
     /**
-     * Register for ServiceState changed. 
+     * Register for ServiceState changed.
      * Message.obj will contain an AsyncResult.
      * AsyncResult.result will be a ServiceState instance
      */
     void registerForServiceStateChanged(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for ServiceStateChange notification. 
+     * Unregisters for ServiceStateChange notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForServiceStateChanged(Handler h);
@@ -394,9 +436,9 @@
     void registerForSuppServiceNotification(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for Supplementary Service notifications. 
+     * Unregisters for Supplementary Service notifications.
      * Extraneous calls are tolerated silently
-     * 
+     *
      * @param h Handler to be removed from the registrant list.
      */
     void unregisterForSuppServiceNotification(Handler h);
@@ -414,53 +456,85 @@
     /**
      * Unregister for notifications when a supplementary service attempt fails.
      * Extraneous calls are tolerated silently
-     * 
+     *
      * @param h Handler to be removed from the registrant list.
      */
     void unregisterForSuppServiceFailed(Handler h);
 
-    /** 
-     * Returns SIM record load state. Use 
+    /**
+     * Register for notifications when a sInCall VoicePrivacy is enabled
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj);
+
+    /**
+     * Unegister for notifications when a sInCall VoicePrivacy is enabled
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    void unregisterForInCallVoicePrivacyOn(Handler h);
+
+    /**
+     * Register for notifications when a sInCall VoicePrivacy is disabled
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj);
+
+    /**
+     * Unegister for notifications when a sInCall VoicePrivacy is disabled
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    void unregisterForInCallVoicePrivacyOff(Handler h);
+
+    /**
+     * Returns SIM record load state. Use
      * <code>getSimCard().registerForReady()</code> for change notification.
      *
-     * @return true if records from the SIM have been loaded and are 
+     * @return true if records from the SIM have been loaded and are
      * available (if applicable). If not applicable to the underlying
      * technology, returns true as well.
      */
-    boolean getSimRecordsLoaded();
+    boolean getIccRecordsLoaded();
 
     /**
-     * Returns the SIM card interface for this phone, or null
+     * Returns the ICC card interface for this phone, or null
      * if not applicable to underlying technology.
      */
-    SimCard getSimCard();
+    IccCard getIccCard();
 
     /**
-     * Answers a ringing or waiting call. Active calls, if any, go on hold. 
+     * Answers a ringing or waiting call. Active calls, if any, go on hold.
      * Answering occurs asynchronously, and final notification occurs via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      *
      * @exception CallStateException when no call is ringing or waiting
      */
     void acceptCall() throws CallStateException;
 
-    /** 
-     * Reject (ignore) a ringing call. In GSM, this means UDUB  
-     * (User Determined User Busy). Reject occurs asynchronously, 
-     * and final notification occurs via 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+    /**
+     * Reject (ignore) a ringing call. In GSM, this means UDUB
+     * (User Determined User Busy). Reject occurs asynchronously,
+     * and final notification occurs via
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      *
      * @exception CallStateException when no call is ringing or waiting
      */
     void rejectCall() throws CallStateException;
 
-    /** 
+    /**
      * Places any active calls on hold, and makes any held calls
      *  active. Switch occurs asynchronously and may fail.
-     * Final notification occurs via 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * Final notification occurs via
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      *
      * @exception CallStateException if a call is ringing, waiting, or
@@ -469,24 +543,40 @@
     void switchHoldingAndActive() throws CallStateException;
 
     /**
-     * Whether or not the phone can conference in the current phone 
+     * Whether or not the phone can conference in the current phone
      * state--that is, one call holding and one call active.
-     * @return true if the phone can conference; false otherwise. 
+     * @return true if the phone can conference; false otherwise.
      */
     boolean canConference();
 
     /**
-     * Conferences holding and active. Conference occurs asynchronously 
-     * and may fail. Final notification occurs via 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
-     * java.lang.Object) registerForPhoneStateChanged()}.    
-     * 
+     * Conferences holding and active. Conference occurs asynchronously
+     * and may fail. Final notification occurs via
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
+     * java.lang.Object) registerForPhoneStateChanged()}.
+     *
      * @exception CallStateException if canConference() would return false.
      * In these cases, this operation may not be performed.
      */
     void conference() throws CallStateException;
 
     /**
+     * Enable or disable enhanced Voice Privacy (VP). If enhanced VP is
+     * disabled, normal VP is enabled.
+     *
+     * @param enable whether true or false to enable or disable.
+     * @param onComplete a callback message when the action is completed.
+     */
+    void enableEnhancedVoicePrivacy(boolean enable, Message onComplete);
+
+    /**
+     * Get the currently set Voice Privacy (VP) mode.
+     *
+     * @param onComplete a callback message when the action is completed.
+     */
+    void getEnhancedVoicePrivacy(Message onComplete);
+
+    /**
      * Whether or not the phone can do explicit call transfer in the current
      * phone state--that is, one call holding and one call active.
      * @return true if the phone can do explicit call transfer; false otherwise.
@@ -513,65 +603,65 @@
     void clearDisconnected();
 
 
-    /** 
-     * Gets the foreground call object, which represents all connections that 
-     * are dialing or active (all connections 
+    /**
+     * Gets the foreground call object, which represents all connections that
+     * are dialing or active (all connections
      * that have their audio path connected).<p>
      *
      * The foreground call is a singleton object. It is constant for the life
      * of this phone. It is never null.<p>
-     * 
+     *
      * The foreground call will only ever be in one of these states:
-     * IDLE, ACTIVE, DIALING, ALERTING, or DISCONNECTED. 
+     * IDLE, ACTIVE, DIALING, ALERTING, or DISCONNECTED.
      *
      * State change notification is available via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      */
     Call getForegroundCall();
 
-    /** 
+    /**
      * Gets the background call object, which represents all connections that
      * are holding (all connections that have been accepted or connected, but
      * do not have their audio path connected). <p>
      *
      * The background call is a singleton object. It is constant for the life
      * of this phone object . It is never null.<p>
-     * 
+     *
      * The background call will only ever be in one of these states:
      * IDLE, HOLDING or DISCONNECTED.
      *
      * State change notification is available via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      */
     Call getBackgroundCall();
 
-    /** 
-     * Gets the ringing call object, which represents an incoming 
+    /**
+     * Gets the ringing call object, which represents an incoming
      * connection (if present) that is pending answer/accept. (This connection
      * may be RINGING or WAITING, and there may be only one.)<p>
 
      * The ringing call is a singleton object. It is constant for the life
      * of this phone. It is never null.<p>
-     * 
+     *
      * The ringing call will only ever be in one of these states:
      * IDLE, INCOMING, WAITING or DISCONNECTED.
      *
      * State change notification is available via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      */
     Call getRingingCall();
 
-    /** 
+    /**
      * Initiate a new voice connection. This happens asynchronously, so you
      * cannot assume the audio path is connected (or a call index has been
      * assigned) until PhoneStateChanged notification has occurred.
      *
      * @exception CallStateException if a new outgoing call is not currently
-     * possible because no more call slots exist or a call exists that is 
-     * dialing, alerting, ringing, or waiting.  Other errors are 
+     * possible because no more call slots exist or a call exists that is
+     * dialing, alerting, ringing, or waiting.  Other errors are
      * handled asynchronously.
      */
     Connection dial(String dialString) throws CallStateException;
@@ -579,7 +669,7 @@
     /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
      * without SEND (so <code>dial</code> is not appropriate).
-     * 
+     *
      * @param dialString the MMI command to be executed.
      * @return true if MMI command is executed.
      */
@@ -597,7 +687,7 @@
     boolean handleInCallMmiCommands(String command) throws CallStateException;
 
     /**
-     * Play a DTMF tone on the active call. Ignored if there is no active call. 
+     * Play a DTMF tone on the active call. Ignored if there is no active call.
      * @param c should be one of 0-9, '*' or '#'. Other values will be
      * silently ignored.
      */
@@ -619,20 +709,20 @@
 
 
     /**
-     * Sets the radio power on/off state (off is sometimes 
-     * called "airplane mode"). Current state can be gotten via 
-     * {@link #getServiceState()}.{@link 
+     * Sets the radio power on/off state (off is sometimes
+     * called "airplane mode"). Current state can be gotten via
+     * {@link #getServiceState()}.{@link
      * android.telephony.ServiceState#getState() getState()}.
-     * <strong>Note: </strong>This request is asynchronous. 
+     * <strong>Note: </strong>This request is asynchronous.
      * getServiceState().getState() will not change immediately after this call.
-     * registerForServiceStateChanged() to find out when the 
+     * registerForServiceStateChanged() to find out when the
      * request is complete.
      *
-     * @param power true means "on", false means "off". 
+     * @param power true means "on", false means "off".
      */
     void setRadioPower(boolean power);
 
-    /** 
+    /**
      * Get voice message waiting indicator status. No change notification
      * available on this interface. Use PhoneStateNotifier or similar instead.
      *
@@ -674,8 +764,8 @@
     void setLine1Number(String alphaTag, String number, Message onComplete);
 
     /**
-     * Get the voice mail access phone number. Typically dialed when the 
-     * user holds the "1" key in the phone app. May return null if not 
+     * Get the voice mail access phone number. Typically dialed when the
+     * user holds the "1" key in the phone app. May return null if not
      * available or the SIM is not ready.<p>
      */
     String getVoiceMailNumber();
@@ -684,8 +774,8 @@
      * Returns the alpha tag associated with the voice mail number.
      * If there is no alpha tag associated or the record is not yet available,
      * returns a default localized string. <p>
-     * 
-     * Please use this value instead of some other localized string when 
+     *
+     * Please use this value instead of some other localized string when
      * showing a name for this number in the UI. For example, call log
      * entries should show this alpha tag. <p>
      *
@@ -708,29 +798,29 @@
 
     /**
      * getCallForwardingOptions
-     * gets a call forwarding option. The return value of 
-     * ((AsyncResult)onComplete.obj) is an array of CallForwardInfo. 
-     * 
-     * @param commandInterfaceCFReason is one of the valid call forwarding 
-     *        CF_REASONS, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
+     * gets a call forwarding option. The return value of
+     * ((AsyncResult)onComplete.obj) is an array of CallForwardInfo.
+     *
+     * @param commandInterfaceCFReason is one of the valid call forwarding
+     *        CF_REASONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
      * @param onComplete a callback message when the action is completed.
-     *        @see com.android.internal.telephony.gsm.CallForwardInfo for details.
+     *        @see com.android.internal.telephony.CallForwardInfo for details.
      */
     void getCallForwardingOption(int commandInterfaceCFReason,
                                   Message onComplete);
-    
+
     /**
      * setCallForwardingOptions
      * sets a call forwarding option.
-     * 
-     * @param commandInterfaceCFReason is one of the valid call forwarding 
-     *        CF_REASONS, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
-     * @param commandInterfaceCFAction is one of the valid call forwarding 
-     *        CF_ACTIONS, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
-     * @param dialingNumber is the target phone number to forward calls to 
+     *
+     * @param commandInterfaceCFReason is one of the valid call forwarding
+     *        CF_REASONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
+     * @param commandInterfaceCFAction is one of the valid call forwarding
+     *        CF_ACTIONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
+     * @param dialingNumber is the target phone number to forward calls to
      * @param timerSeconds is used by CFNRy to indicate the timeout before
      *        forwarding is attempted.
      * @param onComplete a callback message when the action is completed.
@@ -740,83 +830,83 @@
                                  String dialingNumber,
                                  int timerSeconds,
                                  Message onComplete);
-    
+
     /**
      * getOutgoingCallerIdDisplay
-     * gets outgoing caller id display. The return value of 
+     * gets outgoing caller id display. The return value of
      * ((AsyncResult)onComplete.obj) is an array of int, with a length of 2.
-     * 
+     *
      * @param onComplete a callback message when the action is completed.
-     *        @see com.android.internal.telephony.gsm.CommandsInterface.getCLIR for details.
+     *        @see com.android.internal.telephony.CommandsInterface.getCLIR for details.
      */
     void getOutgoingCallerIdDisplay(Message onComplete);
-    
+
     /**
      * setOutgoingCallerIdDisplay
-     * sets a call forwarding option. 
-     * 
-     * @param commandInterfaceCLIRMode is one of the valid call CLIR 
-     *        modes, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
+     * sets a call forwarding option.
+     *
+     * @param commandInterfaceCLIRMode is one of the valid call CLIR
+     *        modes, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
      * @param onComplete a callback message when the action is completed.
      */
     void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
                                     Message onComplete);
-    
+
     /**
      * getCallWaiting
-     * gets call waiting activation state. The return value of 
+     * gets call waiting activation state. The return value of
      * ((AsyncResult)onComplete.obj) is an array of int, with a length of 1.
-     * 
+     *
      * @param onComplete a callback message when the action is completed.
-     *        @see com.android.internal.telephony.gsm.CommandsInterface.queryCallWaiting for details.
+     *        @see com.android.internal.telephony.CommandsInterface.queryCallWaiting for details.
      */
     void getCallWaiting(Message onComplete);
-    
+
     /**
      * setCallWaiting
-     * sets a call forwarding option. 
-     * 
-     * @param enable is a boolean representing the state that you are 
+     * sets a call forwarding option.
+     *
+     * @param enable is a boolean representing the state that you are
      *        requesting, true for enabled, false for disabled.
      * @param onComplete a callback message when the action is completed.
      */
     void setCallWaiting(boolean enable, Message onComplete);
-    
+
     /**
      * Scan available networks. This method is asynchronous; .
      * On completion, <code>response.obj</code> is set to an AsyncResult with
      * one of the following members:.<p>
      *<ul>
-     * <li><code>response.obj.result</code> will be a <code>List</code> of 
-     * <code>com.android.internal.telephony.gsm.NetworkInfo</code> objects, or</li> 
-     * <li><code>response.obj.exception</code> will be set with an exception 
+     * <li><code>response.obj.result</code> will be a <code>List</code> of
+     * <code>com.android.internal.telephony.gsm.NetworkInfo</code> objects, or</li>
+     * <li><code>response.obj.exception</code> will be set with an exception
      * on failure.</li>
      * </ul>
      */
-    void getAvailableNetworks(Message response);    
+    void getAvailableNetworks(Message response);
 
     /**
      * Switches network selection mode to "automatic", re-scanning and
      * re-selecting a network if appropriate.
-     * 
-     * @param response The message to dispatch when the network selection 
+     *
+     * @param response The message to dispatch when the network selection
      * is complete.
-     * 
-     * @see #selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo, 
+     *
+     * @see #selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo,
      * android.os.Message )
      */
     void setNetworkSelectionModeAutomatic(Message response);
 
     /**
-     * Manually selects a network. <code>response</code> is 
+     * Manually selects a network. <code>response</code> is
      * dispatched when this is complete.  <code>response.obj</code> will be
      * an AsyncResult, and <code>response.obj.exception</code> will be non-null
      * on failure.
-     * 
+     *
      * @see #setNetworkSelectionModeAutomatic(Message)
      */
-    void selectNetworkManually(NetworkInfo network, 
+    void selectNetworkManually(NetworkInfo network,
                             Message response);
 
     /**
@@ -843,7 +933,7 @@
      * of available cell IDs.  Cell IDs are in hexadecimal format.
      *
      * @param response callback message that is dispatched when the query
-     * completes. 
+     * completes.
      */
     void getNeighboringCids(Message response);
 
@@ -856,28 +946,28 @@
      * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
      * a Connection object.<p>
      *
-     * Message.arg1 will be the post dial character being processed, 
+     * Message.arg1 will be the post dial character being processed,
      * or 0 ('\0') if end of string.<p>
      *
-     * If Connection.getPostDialState() == WAIT, 
-     * the application must call 
-     * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() 
-     * Connection.proceedAfterWaitChar()} or 
-     * {@link com.android.internal.telephony.Connection#cancelPostDial() 
+     * If Connection.getPostDialState() == WAIT,
+     * the application must call
+     * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
+     * Connection.proceedAfterWaitChar()} or
+     * {@link com.android.internal.telephony.Connection#cancelPostDial()
      * Connection.cancelPostDial()}
-     * for the telephony system to continue playing the post-dial 
+     * for the telephony system to continue playing the post-dial
      * DTMF sequence.<p>
      *
-     * If Connection.getPostDialState() == WILD, 
-     * the application must call 
+     * If Connection.getPostDialState() == WILD,
+     * the application must call
      * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
      * Connection.proceedAfterWildChar()}
-     * or 
-     * {@link com.android.internal.telephony.Connection#cancelPostDial() 
+     * or
+     * {@link com.android.internal.telephony.Connection#cancelPostDial()
      * Connection.cancelPostDial()}
-     * for the telephony system to continue playing the 
+     * for the telephony system to continue playing the
      * post-dial DTMF sequence.<p>
-     * 
+     *
      * Only one post dial character handler may be set. <p>
      * Calling this method with "h" equal to null unsets this handler.<p>
      */
@@ -885,19 +975,19 @@
 
 
     /**
-     * Mutes or unmutes the microphone for the active call. The microphone 
-     * is automatically unmuted if a call is answered, dialed, or resumed 
+     * Mutes or unmutes the microphone for the active call. The microphone
+     * is automatically unmuted if a call is answered, dialed, or resumed
      * from a holding state.
-     * 
-     * @param muted true to mute the microphone, 
+     *
+     * @param muted true to mute the microphone,
      * false to activate the microphone.
      */
 
     void setMute(boolean muted);
 
     /**
-     * Gets current mute status. Use 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * Gets current mute status. Use
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}
      * as a change notifcation, although presently phone state changed is not
      * fired when setMute() is called.
@@ -908,12 +998,12 @@
 
     /**
      * Invokes RIL_REQUEST_OEM_HOOK_RAW on RIL implementation.
-     * 
+     *
      * @param data The data for the request.
-     * @param response <strong>On success</strong>, 
+     * @param response <strong>On success</strong>,
      * (byte[])(((AsyncResult)response.obj).result)
-     * <strong>On failure</strong>, 
-     * (((AsyncResult)response.obj).result) == null and 
+     * <strong>On failure</strong>,
+     * (((AsyncResult)response.obj).result) == null and
      * (((AsyncResult)response.obj).exception) being an instance of
      * com.android.internal.telephony.gsm.CommandException
      *
@@ -923,13 +1013,13 @@
 
     /**
      * Invokes RIL_REQUEST_OEM_HOOK_Strings on RIL implementation.
-     * 
+     *
      * @param strings The strings to make available as the request data.
-     * @param response <strong>On success</strong>, "response" bytes is 
+     * @param response <strong>On success</strong>, "response" bytes is
      * made available as:
      * (String[])(((AsyncResult)response.obj).result).
-     * <strong>On failure</strong>, 
-     * (((AsyncResult)response.obj).result) == null and 
+     * <strong>On failure</strong>,
+     * (((AsyncResult)response.obj).result) == null and
      * (((AsyncResult)response.obj).exception) being an instance of
      * com.android.internal.telephony.gsm.CommandException
      *
@@ -940,6 +1030,7 @@
     /**
      * Get the current active PDP context list
      *
+     * @deprecated
      * @param response <strong>On success</strong>, "response" bytes is
      * made available as:
      * (String[])(((AsyncResult)response.obj).result).
@@ -951,13 +1042,34 @@
     void getPdpContextList(Message response);
 
     /**
+     * Get the current active Data Call list, substitutes getPdpContextList
+     *
+     * @param response <strong>On success</strong>, "response" bytes is
+     * made available as:
+     * (String[])(((AsyncResult)response.obj).result).
+     * <strong>On failure</strong>,
+     * (((AsyncResult)response.obj).result) == null and
+     * (((AsyncResult)response.obj).exception) being an instance of
+     * com.android.internal.telephony.gsm.CommandException
+     */
+    void getDataCallList(Message response);
+
+    /**
      * Get current mutiple PDP link status
-     * 
+     *
+     * @deprecated
      * @return list of pdp link connections
      */
     List<PdpConnection> getCurrentPdpList ();
 
     /**
+     * Get current mutiple data connection status
+     *
+     * @return list of data connections
+     */
+    List<DataConnection> getCurrentDataConnectionList ();
+
+    /**
      * Udpate LAC and CID in service state for currnet GSM netowrk registration
      *
      * If get different LAC and/or CID, notifyServiceState will be sent
@@ -981,11 +1093,11 @@
     void disableLocationUpdates();
 
     /**
-     * For unit tests; don't send notifications to "Phone" 
+     * For unit tests; don't send notifications to "Phone"
      * mailbox registrants if true.
      */
     void setUnitTestMode(boolean f);
-    
+
     /**
      * @return true If unit test mode is enabled
      */
@@ -1019,8 +1131,29 @@
     void setDataRoamingEnabled(boolean enable);
 
     /**
+     *  Query the CDMA roaming preference setting
+     *
+     * @param response is callback message to report one of  CDMA_RM_*
+     */
+    void queryCdmaRoamingPreference(Message response);
+
+    /**
+     *  Requests to set the CDMA roaming preference
+     * @param cdmaRoamingType one of  CDMA_RM_*
+     * @param response is callback message
+     */
+    void setCdmaRoamingPreference(int cdmaRoamingType, Message response);
+
+    /**
+     *  Requests to set the CDMA subscription mode
+     * @param cdmaSubscriptionType one of  CDMA_SUBSCRIPTION_*
+     * @param response is callback message
+     */
+    void setCdmaSubscription(int cdmaSubscriptionType, Message response);
+
+    /**
      * If this is a simulated phone interface, returns a SimulatedRadioControl.
-     * @ return A SimulatedRadioControl if this is a simulated interface; 
+     * @ return A SimulatedRadioControl if this is a simulated interface;
      * otherwise, null.
      */
     SimulatedRadioControl getSimulatedRadioControl();
@@ -1109,7 +1242,7 @@
     public String[] getDnsServers(String apnType);
 
     /**
-     * Retrieves the unique device ID, e.g., IMEI for GSM phones.
+     * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
      */
     String getDeviceId();
 
@@ -1125,7 +1258,81 @@
     String getSubscriberId();
 
     /**
-     * Retrieves the serial number of the SIM, if applicable.
+     * Retrieves the serial number of the ICC, if applicable.
      */
-    String getSimSerialNumber();
+    String getIccSerialNumber();
+
+    //***** CDMA support methods
+
+
+    /**
+     * Retrieves the ESN for CDMA phones.
+     */
+    String getEsn();
+
+    /**
+     * Retrieves MEID for CDMA phones.
+     */
+    String getMeid();
+
+    /**
+     * Retrieves the PhoneSubInfo of the Phone
+     */
+    public PhoneSubInfo getPhoneSubInfo();
+
+    /**
+     * Retrieves the IccSmsInterfaceManager of the Phone
+     */
+    public IccSmsInterfaceManager getIccSmsInterfaceManager();
+
+    /**
+     * Retrieves the IccPhoneBookInterfaceManager of the Phone
+     */
+    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager();
+
+    /**
+     * setTTYModeEnabled
+     * sets a TTY mode option.
+     *
+     * @param enable is a boolean representing the state that you are
+     *        requesting, true for enabled, false for disabled.
+     * @param onComplete a callback message when the action is completed
+     */
+    void setTTYModeEnabled(boolean enable, Message onComplete);
+
+    /**
+     * queryTTYModeEnabled
+     * query the status of the TTY mode
+     *
+     * @param onComplete a callback message when the action is completed.
+     */
+    void queryTTYModeEnabled(Message onComplete);
+
+    /**
+     * Activate or deactivate cell broadcast SMS.
+     *
+     * @param activate
+     *            0 = activate, 1 = deactivate
+     * @param response
+     *            Callback message is empty on completion
+     */
+    void activateCellBroadcastSms(int activate, Message response);
+
+    /**
+     * Query the current configuration of cdma cell broadcast SMS.
+     *
+     * @param response
+     *            Callback message is empty on completion
+     */
+    void getCellBroadcastSmsConfig(Message response);
+
+    /**
+     * Configure cell broadcast SMS.
+     *
+     * @param response
+     *            Callback message is empty on completion
+     */
+    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response);
+
+    public void notifyDataActivity();
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 3571f02..20c54fb 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -20,23 +20,30 @@
 import android.app.IActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.SharedPreferences;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Message;
 import android.os.RegistrantList;
 import android.os.SystemProperties;
+import android.preference.PreferenceManager;
 import android.telephony.ServiceState;
+import android.text.TextUtils;
 import android.util.Log;
+
 import com.android.internal.R;
+import com.android.internal.telephony.gsm.PdpConnection;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 
 import java.util.List;
 import java.util.Locale;
 
+
 /**
- * (<em>Not for SDK use</em>) 
+ * (<em>Not for SDK use</em>)
  * A base implementation for the com.android.internal.telephony.Phone interface.
- * 
+ *
  * Note that implementations of Phone.java are expected to be used
  * from a single application thread. This should be the same thread that
  * originally called PhoneFactory to obtain the interface.
@@ -46,42 +53,101 @@
  */
 
 public abstract class PhoneBase implements Phone {
-    private static final String LOG_TAG = "GSM";
+    private static final String LOG_TAG = "PHONE";
+    private static final boolean LOCAL_DEBUG = true;
 
-    protected final RegistrantList mPhoneStateRegistrants 
+    // Key used to read and write the saved network selection value
+    public static final String NETWORK_SELECTION_KEY = "network_selection_key";
+
+ // Key used to read/write "disable data connection on boot" pref (used for testing)
+    public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
+
+    //***** Event Constants
+    protected static final int EVENT_RADIO_AVAILABLE             = 1;
+    /** Supplementary Service Notification received. */
+    protected static final int EVENT_SSN                         = 2;
+    protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
+    protected static final int EVENT_MMI_DONE                    = 4;
+    protected static final int EVENT_RADIO_ON                    = 5;
+    protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
+    protected static final int EVENT_USSD                        = 7;
+    protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
+    protected static final int EVENT_GET_IMEI_DONE               = 9;
+    protected static final int EVENT_GET_IMEISV_DONE             = 10;
+    protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
+    protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
+    protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
+    protected static final int EVENT_CALL_RING                   = 14;
+    // Used to intercept the carrier selection calls so that
+    // we can save the values.
+    protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 15;
+    protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 16;
+    protected static final int EVENT_SET_CLIR_COMPLETE              = 17;
+    protected static final int EVENT_REGISTERED_TO_NETWORK          = 18;
+    protected static final int EVENT_SET_VM_NUMBER_DONE             = 19;
+    // Events for CDMA support
+    protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 20;
+    protected static final int EVENT_RUIM_RECORDS_LOADED            = 21;
+    protected static final int EVENT_NV_READY                       = 22;
+    protected static final int EVENT_SET_ENHANCED_VP                = 23;
+
+    // Key used to read/write current CLIR setting
+    public static final String CLIR_KEY = "clir_key";
+
+    // Key used to read/write "disable DNS server check" pref (used for testing)
+    public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
+
+    //***** Instance Variables
+    public CommandsInterface mCM;
+    protected IccFileHandler mIccFileHandler;
+    boolean mDnsCheckDisabled = false;
+
+    /**
+     * Set a system property, unless we're in unit test mode
+     */
+    public void
+    setSystemProperty(String property, String value) {
+        if(getUnitTestMode()) {
+            return;
+        }
+        SystemProperties.set(property, value);
+    }
+
+
+    protected final RegistrantList mPhoneStateRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mNewRingingConnectionRegistrants 
+    protected final RegistrantList mNewRingingConnectionRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mIncomingRingRegistrants 
-            = new RegistrantList();
-    
-    protected final RegistrantList mDisconnectRegistrants 
+    protected final RegistrantList mIncomingRingRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mServiceStateRegistrants 
-            = new RegistrantList();
-    
-    protected final RegistrantList mMmiCompleteRegistrants 
+    protected final RegistrantList mDisconnectRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mMmiRegistrants 
+    protected final RegistrantList mServiceStateRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mUnknownConnectionRegistrants 
+    protected final RegistrantList mMmiCompleteRegistrants
             = new RegistrantList();
-    
-    protected final RegistrantList mSuppServiceFailedRegistrants 
+
+    protected final RegistrantList mMmiRegistrants
             = new RegistrantList();
-    
+
+    protected final RegistrantList mUnknownConnectionRegistrants
+            = new RegistrantList();
+
+    protected final RegistrantList mSuppServiceFailedRegistrants
+            = new RegistrantList();
+
     protected Looper mLooper; /* to insure registrants are in correct thread*/
 
     protected Context mContext;
 
-    /** 
-     * PhoneNotifier is an abstraction for all system-wide 
-     * state change notification. DefaultPhoneNotifier is 
+    /**
+     * PhoneNotifier is an abstraction for all system-wide
+     * state change notification. DefaultPhoneNotifier is
      * used here unless running we're inside a unit test.
      */
     protected PhoneNotifier mNotifier;
@@ -94,7 +160,7 @@
      * Constructs a PhoneBase in normal (non-unit test) mode.
      *
      * @param context Context object from hosting application
-     * @param notifier An instance of DefaultPhoneNotifier, 
+     * @param notifier An instance of DefaultPhoneNotifier,
      * unless unit testing.
      */
     protected PhoneBase(PhoneNotifier notifier, Context context) {
@@ -105,13 +171,13 @@
      * Constructs a PhoneBase in normal (non-unit test) mode.
      *
      * @param context Context object from hosting application
-     * @param notifier An instance of DefaultPhoneNotifier, 
+     * @param notifier An instance of DefaultPhoneNotifier,
      * unless unit testing.
-     * @param unitTestMode when true, prevents notifications 
+     * @param unitTestMode when true, prevents notifications
      * of state change events
      */
-    protected PhoneBase(PhoneNotifier notifier, Context context, 
-                         boolean unitTestMode) {
+    protected PhoneBase(PhoneNotifier notifier, Context context,
+            boolean unitTestMode) {
         this.mNotifier = notifier;
         this.mContext = context;
         mLooper = Looper.myLooper();
@@ -119,6 +185,9 @@
         setLocaleByCarrier();
 
         setUnitTestMode(unitTestMode);
+
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);        
     }
 
     // Inherited documentation suffices.
@@ -126,6 +195,26 @@
         return mContext;
     }
 
+    /**
+     * Disables the DNS check (i.e., allows "0.0.0.0").
+     * Useful for lab testing environment.
+     * @param b true disables the check, false enables.
+     */
+    public void disableDnsCheck(boolean b) {
+        mDnsCheckDisabled = b;
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);        
+        editor.commit();
+    }
+
+    /**
+     * Returns true if the DNS check is currently disabled.
+     */
+    public boolean isDnsCheckDisabled() {
+        return mDnsCheckDisabled;
+    }
+
     // Inherited documentation suffices.
     public void registerForPhoneStateChanged(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -137,29 +226,29 @@
     public void unregisterForPhoneStateChanged(Handler h) {
         mPhoneStateRegistrants.remove(h);
     }
-    
+
     /**
      * Notify registrants of a PhoneStateChanged.
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
     protected void notifyCallStateChangedP() {
         AsyncResult ar = new AsyncResult(null, this, null);
         mPhoneStateRegistrants.notifyRegistrants(ar);
     }
-     
+
     // Inherited documentation suffices.
     public void registerForUnknownConnection(Handler h, int what, Object obj) {
         checkCorrectThread(h);
-        
+
         mUnknownConnectionRegistrants.addUnique(h, what, obj);
     }
-    
+
     // Inherited documentation suffices.
     public void unregisterForUnknownConnection(Handler h) {
         mUnknownConnectionRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForNewRingingConnection(
             Handler h, int what, Object obj) {
@@ -173,12 +262,33 @@
         mNewRingingConnectionRegistrants.remove(h);
     }
 
+    // Inherited documentation suffices.
+    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
+        mCM.registerForInCallVoicePrivacyOn(h,what,obj);
+    }
+
+    // Inherited documentation suffices.
+    public void unregisterForInCallVoicePrivacyOn(Handler h){
+        mCM.unregisterForInCallVoicePrivacyOn(h);
+    }
+
+    // Inherited documentation suffices.
+    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
+        mCM.registerForInCallVoicePrivacyOff(h,what,obj);
+    }
+
+    // Inherited documentation suffices.
+    public void unregisterForInCallVoicePrivacyOff(Handler h){
+        mCM.unregisterForInCallVoicePrivacyOff(h);
+    }
+
+
     /**
      * Notifiy registrants of a new ringing Connection.
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
-    protected void notifyNewRingingConnectionP(Connection cn) {    
+    protected void notifyNewRingingConnectionP(Connection cn) {
         AsyncResult ar = new AsyncResult(null, cn, null);
         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
     }
@@ -187,15 +297,15 @@
     public void registerForIncomingRing(
             Handler h, int what, Object obj) {
         checkCorrectThread(h);
-        
+
         mIncomingRingRegistrants.addUnique(h, what, obj);
     }
-    
+
     // Inherited documentation suffices.
     public void unregisterForIncomingRing(Handler h) {
         mIncomingRingRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForDisconnect(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -211,15 +321,15 @@
     // Inherited documentation suffices.
     public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
         checkCorrectThread(h);
-        
+
         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
     }
-    
+
     // Inherited documentation suffices.
     public void unregisterForSuppServiceFailed(Handler h) {
         mSuppServiceFailedRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForMmiInitiate(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -231,7 +341,7 @@
     public void unregisterForMmiInitiate(Handler h) {
         mMmiRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForMmiComplete(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -247,10 +357,31 @@
     }
 
     /**
-     * Subclasses should override this. See documentation in superclass.
+     * Method to retrieve the saved operator id from the Shared Preferences
      */
-    public abstract List getPendingMmiCodes();
-    
+    private String getSavedNetworkSelection() {
+        // open the shared preferences and search with our key.
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+        return sp.getString(NETWORK_SELECTION_KEY, "");
+    }
+
+    /**
+     * Method to restore the previously saved operator id, or reset to
+     * automatic selection, all depending upon the value in the shared
+     * preferences.
+     */
+    public void restoreSavedNetworkSelection(Message response) {
+        // retrieve the operator id
+        String networkSelection = getSavedNetworkSelection();
+
+        // set to auto if the id is empty, otherwise select the network.
+        if (TextUtils.isEmpty(networkSelection)) {
+            mCM.setNetworkSelectionModeAutomatic(response);
+        } else {
+            mCM.setNetworkSelectionModeManual(networkSelection, response);
+        }
+    }
+
     // Inherited documentation suffices.
     public void setUnitTestMode(boolean f) {
         mUnitTestMode = f;
@@ -260,11 +391,11 @@
     public boolean getUnitTestMode() {
         return mUnitTestMode;
     }
-    
+
     /**
      * To be invoked when a voice call Connection disconnects.
      *
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
     protected void notifyDisconnectP(Connection cn) {
@@ -286,7 +417,7 @@
     }
 
     /**
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
     protected void notifyServiceStateChangedP(ServiceState ss) {
@@ -312,7 +443,7 @@
     private void checkCorrectThread(Handler h) {
         if (h.getLooper() != mLooper) {
             throw new RuntimeException(
-                "com.android.internal.telephony.Phone must be used from within one thread");
+                    "com.android.internal.telephony.Phone must be used from within one thread");
         }
     }
 
@@ -401,4 +532,107 @@
             }
         }
     }
+
+    /*
+     * Retrieves the Handler of the Phone instance
+     */
+    public abstract Handler getHandler();
+
+    /**
+     * Retrieves the IccFileHandler of the Phone instance
+     */
+    public abstract IccFileHandler getIccFileHandler();
+
+
+    /**
+     *  Query the status of the CDMA roaming preference
+     */
+    public void queryCdmaRoamingPreference(Message response) {
+        mCM.queryCdmaRoamingPreference(response);
+    }
+
+    /**
+     *  Set the status of the CDMA roaming preference
+     */
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
+    }
+
+    /**
+     *  Set the status of the CDMA subscription mode
+     */
+    public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
+        mCM.setCdmaSubscription(cdmaSubscriptionType, response);
+    }
+
+    /**
+     *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
+     */
+    public void setPreferredNetworkType(int networkType, Message response) {
+        mCM.setPreferredNetworkType(networkType, response);
+    }
+
+    /**
+     *  Set the status of the preferred Network Type: Global, CDMA only or GSM/UMTS only
+     */
+    public void getPreferredNetworkType(Message response) {
+        mCM.getPreferredNetworkType(response);
+    }
+
+    public void setTTYModeEnabled(boolean enable, Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    public void queryTTYModeEnabled(Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    /**
+     * This should only be called in GSM mode.
+     * Only here for some backward compatibility
+     * issues concerning the GSMPhone class.
+     * @deprecated
+     */
+    public List<PdpConnection> getCurrentPdpList() {
+        return null;
+    }
+
+    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    public void getEnhancedVoicePrivacy(Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    public void setBandMode(int bandMode, Message response) {
+        mCM.setBandMode(bandMode, response);
+    }
+
+    public void queryAvailableBandMode(Message response) {
+        mCM.queryAvailableBandMode(response);
+    }
+
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
+        mCM.invokeOemRilRequestRaw(data, response);
+    }
+
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
+        mCM.invokeOemRilRequestStrings(strings, response);
+    }
+
+    public void notifyDataActivity() {
+        mNotifier.notifyDataActivity(this);
+    }
+
+    public void notifyDataConnection(String reason) {
+        mNotifier.notifyDataConnection(this, reason);
+    }
+
+    public abstract String getPhoneName();
+
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 0ca5f45..86e2f04 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -16,80 +16,55 @@
 
 package com.android.internal.telephony;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-
-import java.util.Collections;
-
-import android.util.Log;
-import com.android.internal.telephony.gsm.GSMPhone;
-import com.android.internal.telephony.gsm.RIL;
-import com.android.internal.telephony.test.ModelInterpreter;
-import com.android.internal.telephony.test.SimulatedCommands;
-import android.os.Looper;
-import android.os.SystemProperties;
 import android.content.Context;
-import android.content.Intent;
 import android.net.LocalServerSocket;
-import android.app.ActivityManagerNative;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.gsm.GSMPhone;
 
 /**
  * {@hide}
  */
-public class PhoneFactory
-{
-    static final String LOG_TAG="GSM";
-
+public class PhoneFactory {
+    static final String LOG_TAG = "PHONE";
     static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
     static final int SOCKET_OPEN_MAX_RETRY = 3;
-    //***** Class Variables 
+    //***** Class Variables
 
-    static private ArrayList<Phone> sPhones = new ArrayList<Phone>();
+    static private Phone sProxyPhone = null;
+    static private CommandsInterface sCommandsInterface = null;
 
     static private boolean sMadeDefaults = false;
     static private PhoneNotifier sPhoneNotifier;
     static private Looper sLooper;
+    static private Context sContext;
 
-    static private Object testMailbox;
+    static final int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
+
+    static final int preferredCdmaSubscription = RILConstants.PREFERRED_CDMA_SUBSCRIPTION;
 
     //***** Class Methods
 
-    private static void
-    useNewRIL(Context context)
-    {
-        ModelInterpreter mi = null;
-        GSMPhone phone;
-
-        try {
-            if (false) {
-                mi = new ModelInterpreter(new InetSocketAddress("127.0.0.1", 6502));
-            }
-            
-            phone = new GSMPhone(context, new RIL(context), sPhoneNotifier);
-
-            registerPhone (phone);
-        } catch (IOException ex) {
-            Log.e(LOG_TAG, "Error creating ModelInterpreter", ex);
-        }
+    public static void makeDefaultPhones(Context context) {
+        makeDefaultPhone(context);
     }
 
-
     /**
      * FIXME replace this with some other way of making these
      * instances
      */
-    public static void 
-    makeDefaultPhones(Context context)
-    {
-        synchronized(Phone.class) {        
-            if (!sMadeDefaults) {  
+    public static void makeDefaultPhone(Context context) {
+        synchronized(Phone.class) {
+            if (!sMadeDefaults) {
                 sLooper = Looper.myLooper();
+                sContext = context;
 
                 if (sLooper == null) {
                     throw new RuntimeException(
-                        "PhoneFactory.makeDefaultPhones must be called from Looper thread");
+                        "PhoneFactory.makeDefaultPhone must be called from Looper thread");
                 }
 
                 int retryCount = 0;
@@ -109,7 +84,7 @@
                         break;
                     } else if (retryCount > SOCKET_OPEN_MAX_RETRY) {
                         throw new RuntimeException("PhoneFactory probably already running");
-                    }else {
+                    } else {
                         try {
                             Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
                         } catch (InterruptedException er) {
@@ -119,44 +94,66 @@
 
                 sPhoneNotifier = new DefaultPhoneNotifier();
 
-                if ((SystemProperties.get("ro.radio.noril","")).equals("")) {
-                    useNewRIL(context);
-                } else {
-                    GSMPhone phone;
-                    phone = new GSMPhone(context, new SimulatedCommands(), sPhoneNotifier);
-                    registerPhone (phone);
-                }
+                //Get preferredNetworkMode from Settings.System
+                int networkMode = Settings.Secure.getInt(context.getContentResolver(),
+                        Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode);
+                Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
 
+                //Get preferredNetworkMode from Settings.System
+                int cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(),
+                        Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, preferredCdmaSubscription);
+                Log.i(LOG_TAG, "Cdma Subscription set to " + Integer.toString(cdmaSubscription));
+
+                //reads the system properties and makes commandsinterface
+                sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
+
+                switch(networkMode) {
+                    case RILConstants.NETWORK_MODE_CDMA:
+                    case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+                    case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+                    case RILConstants.NETWORK_MODE_GLOBAL:
+                        sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating CDMAPhone");
+                        break;
+                    case RILConstants.NETWORK_MODE_WCDMA_PREF:
+                    case RILConstants.NETWORK_MODE_GSM_ONLY:
+                    case RILConstants.NETWORK_MODE_WCDMA_ONLY:
+                    case RILConstants.NETWORK_MODE_GSM_UMTS:
+                    default:
+                        sProxyPhone = new PhoneProxy(new GSMPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating GSMPhone");
+                        break;
+                }
                 sMadeDefaults = true;
             }
         }
     }
 
-    public static Phone getDefaultPhone()
-    {
+    public static Phone getDefaultPhone() {
+        if (sLooper != Looper.myLooper()) {
+            throw new RuntimeException(
+                "PhoneFactory.getDefaultPhone must be called from Looper thread");
+        }
+
         if (!sMadeDefaults) {
             throw new IllegalStateException("Default phones haven't been made yet!");
         }
+       return sProxyPhone;
+    }
 
-        if (sLooper != Looper.myLooper()) {
-            throw new RuntimeException(
-                "PhoneFactory.getDefaultPhone must be called from Looper thread");
-        }
-
-        synchronized (sPhones) {
-            return sPhones.isEmpty() ? null : sPhones.get(0);
+    public static Phone getCdmaPhone() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+            Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
+            return phone;
         }
     }
-    
-    public static void registerPhone(Phone p)
-    {
-        if (sLooper != Looper.myLooper()) {
-            throw new RuntimeException(
-                "PhoneFactory.getDefaultPhone must be called from Looper thread");
-        }
-        synchronized (sPhones) {
-            sPhones.add(p);
+
+    public static Phone getGsmPhone() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+            Phone phone = new GSMPhone(sContext, sCommandsInterface, sPhoneNotifier);
+            return phone;
         }
     }
 }
-
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
new file mode 100644
index 0000000..dd36f0b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.telephony.CellLocation;
+import android.telephony.ServiceState;
+import android.util.Log;
+
+import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.gsm.NetworkInfo;
+import com.android.internal.telephony.gsm.PdpConnection;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+
+import java.util.List;
+
+public class PhoneProxy extends Handler implements Phone {
+    public final static Object lockForRadioTechnologyChange = new Object();
+//    private static boolean radioTechnologyChangeGsmToCdma = false;
+//    private static boolean radioTechnologyChangeCdmaToGsm = false;
+
+    private Phone mActivePhone;
+    private String mOutgoingPhone;
+    private CommandsInterface mCommandsInterface;
+    private IccSmsInterfaceManagerProxy mIccSmsInterfaceManagerProxy;
+    private IccPhoneBookInterfaceManagerProxy mIccPhoneBookInterfaceManagerProxy;
+    private PhoneSubInfoProxy mPhoneSubInfoProxy;
+
+    private static final int EVENT_RADIO_TECHNOLOGY_CHANGED = 1;
+    private static final String LOG_TAG = "PHONE";
+
+    //***** Class Methods
+    public PhoneProxy(Phone phone) {
+        mActivePhone = phone;
+        mIccSmsInterfaceManagerProxy = new IccSmsInterfaceManagerProxy(
+                phone.getIccSmsInterfaceManager());
+        mIccPhoneBookInterfaceManagerProxy = new IccPhoneBookInterfaceManagerProxy(
+                phone.getIccPhoneBookInterfaceManager());
+        mPhoneSubInfoProxy = new PhoneSubInfoProxy(phone.getPhoneSubInfo());
+        mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
+        mCommandsInterface.registerForRadioTechnologyChanged(
+                this, EVENT_RADIO_TECHNOLOGY_CHANGED, null);
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        switch(msg.what) {
+        case EVENT_RADIO_TECHNOLOGY_CHANGED:
+            //switch Phone from CDMA to GSM or vice versa
+            mOutgoingPhone = ((PhoneBase)mActivePhone).getPhoneName();
+            logd("Switching phone from " + mOutgoingPhone + "Phone to " +
+                    (mOutgoingPhone.equals("GSM") ? "CDMAPhone" : "GSMPhone") );
+            boolean oldPowerState = false; //old power state to off
+            if (mCommandsInterface.getRadioState().isOn()) {
+                oldPowerState = true;
+                logd("Setting Radio Power to Off");
+                mCommandsInterface.setRadioPower(false, null);
+            }
+            if(mOutgoingPhone.equals("GSM")) {
+                logd("Make a new CDMAPhone and destroy the old GSMPhone.");
+
+                ((GSMPhone)mActivePhone).dispose();
+                Phone oldPhone = mActivePhone;
+
+                //Give the garbage collector a hint to start the garbage collection asap
+                // NOTE this has been disabled since radio technology change could happen during
+                //   e.g. a multimedia playing and could slow the system. Tests needs to be done
+                //   to see the effects of the GC call here when system is busy.
+                //System.gc();
+
+                mActivePhone = PhoneFactory.getCdmaPhone();
+                logd("Resetting Radio");
+                mCommandsInterface.setRadioPower(oldPowerState, null);
+                ((GSMPhone)oldPhone).removeReferences();
+                oldPhone = null;
+            } else {
+                logd("Make a new GSMPhone and destroy the old CDMAPhone.");
+
+                ((CDMAPhone)mActivePhone).dispose();
+                //mActivePhone = null;
+                Phone oldPhone = mActivePhone;
+
+                // Give the GC a hint to start the garbage collection asap
+                // NOTE this has been disabled since radio technology change could happen during
+                //   e.g. a multimedia playing and could slow the system. Tests needs to be done
+                //   to see the effects of the GC call here when system is busy.
+                //System.gc();
+
+                mActivePhone = PhoneFactory.getGsmPhone();
+                logd("Resetting Radio:");
+                mCommandsInterface.setRadioPower(oldPowerState, null);
+                ((CDMAPhone)oldPhone).removeReferences();
+                oldPhone = null;
+            }
+
+            //Set the new interfaces in the proxy's
+            mIccSmsInterfaceManagerProxy.setmIccSmsInterfaceManager(
+                    mActivePhone.getIccSmsInterfaceManager());
+            mIccPhoneBookInterfaceManagerProxy.setmIccPhoneBookInterfaceManager(
+                    mActivePhone.getIccPhoneBookInterfaceManager());
+            mPhoneSubInfoProxy.setmPhoneSubInfo(this.mActivePhone.getPhoneSubInfo());
+            mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
+
+            //Send an Intent to the PhoneApp that we had a radio technology change
+            Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+            intent.putExtra(Phone.PHONE_NAME_KEY, mActivePhone.getPhoneName());
+            ActivityManagerNative.broadcastStickyIntent(intent, null);
+
+            break;
+        default:
+            Log.e(LOG_TAG, "Error! This handler was not registered for this message type. Message: "
+                    + msg.what);
+        break;
+        }
+        super.handleMessage(msg);
+    }
+
+    private void logv(String msg) {
+        Log.v(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+    private void logd(String msg) {
+        Log.d(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+    private void logw(String msg) {
+        Log.w(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+    private void loge(String msg) {
+        Log.e(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+
+    public ServiceState getServiceState() {
+        return mActivePhone.getServiceState();
+    }
+
+    public CellLocation getCellLocation() {
+        return mActivePhone.getCellLocation();
+    }
+
+    public DataState getDataConnectionState() {
+        return mActivePhone.getDataConnectionState();
+    }
+
+    public DataActivityState getDataActivityState() {
+        return mActivePhone.getDataActivityState();
+    }
+
+    public Context getContext() {
+        return mActivePhone.getContext();
+    }
+
+    public void disableDnsCheck(boolean b) {
+        mActivePhone.disableDnsCheck(b);
+    }
+
+    public boolean isDnsCheckDisabled() {
+        return mActivePhone.isDnsCheckDisabled();
+    }
+
+    public State getState() {
+        return mActivePhone.getState();
+    }
+
+    public String getPhoneName() {
+        return mActivePhone.getPhoneName();
+    }
+
+    public String[] getActiveApnTypes() {
+        return mActivePhone.getActiveApnTypes();
+    }
+
+    public String getActiveApn() {
+        return mActivePhone.getActiveApn();
+    }
+
+    public int getSignalStrengthASU() {
+        return mActivePhone.getSignalStrengthASU();
+    }
+
+    public void registerForUnknownConnection(Handler h, int what, Object obj) {
+        mActivePhone.registerForUnknownConnection(h, what, obj);
+    }
+
+    public void unregisterForUnknownConnection(Handler h) {
+        mActivePhone.unregisterForUnknownConnection(h);
+    }
+
+    public void registerForPhoneStateChanged(Handler h, int what, Object obj) {
+        mActivePhone.registerForPhoneStateChanged(h, what, obj);
+    }
+
+    public void unregisterForPhoneStateChanged(Handler h) {
+        mActivePhone.unregisterForPhoneStateChanged(h);
+    }
+
+    public void registerForNewRingingConnection(Handler h, int what, Object obj) {
+        mActivePhone.registerForNewRingingConnection(h, what, obj);
+    }
+
+    public void unregisterForNewRingingConnection(Handler h) {
+        mActivePhone.unregisterForNewRingingConnection(h);
+    }
+
+    public void registerForIncomingRing(Handler h, int what, Object obj) {
+        mActivePhone.registerForIncomingRing(h, what, obj);
+    }
+
+    public void unregisterForIncomingRing(Handler h) {
+        mActivePhone.unregisterForIncomingRing(h);
+    }
+
+    public void registerForDisconnect(Handler h, int what, Object obj) {
+        mActivePhone.registerForDisconnect(h, what, obj);
+    }
+
+    public void unregisterForDisconnect(Handler h) {
+        mActivePhone.unregisterForDisconnect(h);
+    }
+
+    public void registerForMmiInitiate(Handler h, int what, Object obj) {
+        mActivePhone.registerForMmiInitiate(h, what, obj);
+    }
+
+    public void unregisterForMmiInitiate(Handler h) {
+        mActivePhone.unregisterForMmiInitiate(h);
+    }
+
+    public void registerForMmiComplete(Handler h, int what, Object obj) {
+        mActivePhone.registerForMmiComplete(h, what, obj);
+    }
+
+    public void unregisterForMmiComplete(Handler h) {
+        mActivePhone.unregisterForMmiComplete(h);
+    }
+
+    public List<? extends MmiCode> getPendingMmiCodes() {
+        return mActivePhone.getPendingMmiCodes();
+    }
+
+    public void sendUssdResponse(String ussdMessge) {
+        mActivePhone.sendUssdResponse(ussdMessge);
+    }
+
+    public void registerForServiceStateChanged(Handler h, int what, Object obj) {
+        mActivePhone.registerForServiceStateChanged(h, what, obj);
+    }
+
+    public void unregisterForServiceStateChanged(Handler h) {
+        mActivePhone.unregisterForServiceStateChanged(h);
+    }
+
+    public void registerForSuppServiceNotification(Handler h, int what, Object obj) {
+        mActivePhone.registerForSuppServiceNotification(h, what, obj);
+    }
+
+    public void unregisterForSuppServiceNotification(Handler h) {
+        mActivePhone.unregisterForSuppServiceNotification(h);
+    }
+
+    public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
+        mActivePhone.registerForSuppServiceFailed(h, what, obj);
+    }
+
+    public void unregisterForSuppServiceFailed(Handler h) {
+        mActivePhone.unregisterForSuppServiceFailed(h);
+    }
+
+    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
+        mActivePhone.registerForInCallVoicePrivacyOn(h,what,obj);
+    }
+
+    public void unregisterForInCallVoicePrivacyOn(Handler h){
+        mActivePhone.unregisterForInCallVoicePrivacyOn(h);
+    }
+
+    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
+        mActivePhone.registerForInCallVoicePrivacyOff(h,what,obj);
+    }
+
+    public void unregisterForInCallVoicePrivacyOff(Handler h){
+        mActivePhone.unregisterForInCallVoicePrivacyOff(h);
+    }
+
+    public boolean getIccRecordsLoaded() {
+        return mActivePhone.getIccRecordsLoaded();
+    }
+
+    public IccCard getIccCard() {
+        return mActivePhone.getIccCard();
+    }
+
+    public void acceptCall() throws CallStateException {
+        mActivePhone.acceptCall();
+    }
+
+    public void rejectCall() throws CallStateException {
+        mActivePhone.rejectCall();
+    }
+
+    public void switchHoldingAndActive() throws CallStateException {
+        mActivePhone.switchHoldingAndActive();
+    }
+
+    public boolean canConference() {
+        return mActivePhone.canConference();
+    }
+
+    public void conference() throws CallStateException {
+        mActivePhone.conference();
+    }
+
+    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
+        mActivePhone.enableEnhancedVoicePrivacy(enable, onComplete);
+    }
+
+    public void getEnhancedVoicePrivacy(Message onComplete) {
+        mActivePhone.getEnhancedVoicePrivacy(onComplete);
+    }
+
+    public boolean canTransfer() {
+        return mActivePhone.canTransfer();
+    }
+
+    public void explicitCallTransfer() throws CallStateException {
+        mActivePhone.explicitCallTransfer();
+    }
+
+    public void clearDisconnected() {
+        mActivePhone.clearDisconnected();
+    }
+
+    public Call getForegroundCall() {
+        return mActivePhone.getForegroundCall();
+    }
+
+    public Call getBackgroundCall() {
+        return mActivePhone.getBackgroundCall();
+    }
+
+    public Call getRingingCall() {
+        return mActivePhone.getRingingCall();
+    }
+
+    public Connection dial(String dialString) throws CallStateException {
+        return mActivePhone.dial(dialString);
+    }
+
+    public boolean handlePinMmi(String dialString) {
+        return mActivePhone.handlePinMmi(dialString);
+    }
+
+    public boolean handleInCallMmiCommands(String command) throws CallStateException {
+        return mActivePhone.handleInCallMmiCommands(command);
+    }
+
+    public void sendDtmf(char c) {
+        mActivePhone.sendDtmf(c);
+    }
+
+    public void startDtmf(char c) {
+        mActivePhone.startDtmf(c);
+    }
+
+    public void stopDtmf() {
+        mActivePhone.stopDtmf();
+    }
+
+    public void setRadioPower(boolean power) {
+        mActivePhone.setRadioPower(power);
+    }
+
+    public boolean getMessageWaitingIndicator() {
+        return mActivePhone.getMessageWaitingIndicator();
+    }
+
+    public boolean getCallForwardingIndicator() {
+        return mActivePhone.getCallForwardingIndicator();
+    }
+
+    public String getLine1Number() {
+        return mActivePhone.getLine1Number();
+    }
+
+    public String getLine1AlphaTag() {
+        return mActivePhone.getLine1AlphaTag();
+    }
+
+    public void setLine1Number(String alphaTag, String number, Message onComplete) {
+        mActivePhone.setLine1Number(alphaTag, number, onComplete);
+    }
+
+    public String getVoiceMailNumber() {
+        return mActivePhone.getVoiceMailNumber();
+    }
+
+    public String getVoiceMailAlphaTag() {
+        return mActivePhone.getVoiceMailAlphaTag();
+    }
+
+    public void setVoiceMailNumber(String alphaTag,String voiceMailNumber,
+            Message onComplete) {
+        mActivePhone.setVoiceMailNumber(alphaTag, voiceMailNumber, onComplete);
+    }
+
+    public void getCallForwardingOption(int commandInterfaceCFReason,
+            Message onComplete) {
+        mActivePhone.getCallForwardingOption(commandInterfaceCFReason,
+                onComplete);
+    }
+
+    public void setCallForwardingOption(int commandInterfaceCFReason,
+            int commandInterfaceCFAction, String dialingNumber,
+            int timerSeconds, Message onComplete) {
+        mActivePhone.setCallForwardingOption(commandInterfaceCFReason,
+            commandInterfaceCFAction, dialingNumber, timerSeconds, onComplete);
+    }
+
+    public void getOutgoingCallerIdDisplay(Message onComplete) {
+        mActivePhone.getOutgoingCallerIdDisplay(onComplete);
+    }
+
+    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
+            Message onComplete) {
+        mActivePhone.setOutgoingCallerIdDisplay(commandInterfaceCLIRMode,
+                onComplete);
+    }
+
+    public void getCallWaiting(Message onComplete) {
+        mActivePhone.getCallWaiting(onComplete);
+    }
+
+    public void setCallWaiting(boolean enable, Message onComplete) {
+        mActivePhone.setCallWaiting(enable, onComplete);
+    }
+
+    public void getAvailableNetworks(Message response) {
+        mActivePhone.getAvailableNetworks(response);
+    }
+
+    public void setNetworkSelectionModeAutomatic(Message response) {
+        mActivePhone.setNetworkSelectionModeAutomatic(response);
+    }
+
+    public void selectNetworkManually(NetworkInfo network, Message response) {
+        mActivePhone.selectNetworkManually(network, response);
+    }
+
+    public void setPreferredNetworkType(int networkType, Message response) {
+        mActivePhone.setPreferredNetworkType(networkType, response);
+    }
+
+    public void getPreferredNetworkType(Message response) {
+        mActivePhone.getPreferredNetworkType(response);
+    }
+
+    public void getNeighboringCids(Message response) {
+        mActivePhone.getNeighboringCids(response);
+    }
+
+    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
+        mActivePhone.setOnPostDialCharacter(h, what, obj);
+    }
+
+    public void setMute(boolean muted) {
+        mActivePhone.setMute(muted);
+    }
+
+    public boolean getMute() {
+        return mActivePhone.getMute();
+    }
+
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
+        mActivePhone.invokeOemRilRequestRaw(data, response);
+    }
+
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
+        mActivePhone.invokeOemRilRequestStrings(strings, response);
+    }
+
+    /**
+     * @deprecated
+     */
+    public void getPdpContextList(Message response) {
+        mActivePhone.getPdpContextList(response);
+    }
+
+    public void getDataCallList(Message response) {
+        mActivePhone.getDataCallList(response);
+    }
+
+    /**
+     * @deprecated
+     */
+    public List<PdpConnection> getCurrentPdpList() {
+        return mActivePhone.getCurrentPdpList();
+    }
+
+    public List<DataConnection> getCurrentDataConnectionList() {
+        return mActivePhone.getCurrentDataConnectionList();
+    }
+
+    public void updateServiceLocation(Message response) {
+        mActivePhone.updateServiceLocation(response);
+    }
+
+    public void enableLocationUpdates() {
+        mActivePhone.enableLocationUpdates();
+    }
+
+    public void disableLocationUpdates() {
+        mActivePhone.disableLocationUpdates();
+    }
+
+    public void setUnitTestMode(boolean f) {
+        mActivePhone.setUnitTestMode(f);
+    }
+
+    public boolean getUnitTestMode() {
+        return mActivePhone.getUnitTestMode();
+    }
+
+    public void setBandMode(int bandMode, Message response) {
+        mActivePhone.setBandMode(bandMode, response);
+    }
+
+    public void queryAvailableBandMode(Message response) {
+        mActivePhone.queryAvailableBandMode(response);
+    }
+
+    public boolean getDataRoamingEnabled() {
+        return mActivePhone.getDataRoamingEnabled();
+    }
+
+    public void setDataRoamingEnabled(boolean enable) {
+        mActivePhone.setDataRoamingEnabled(enable);
+    }
+
+    public void queryCdmaRoamingPreference(Message response) {
+        mActivePhone.queryCdmaRoamingPreference(response);
+    }
+
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        mActivePhone.setCdmaRoamingPreference(cdmaRoamingType, response);
+    }
+
+    public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
+        mActivePhone.setCdmaSubscription(cdmaSubscriptionType, response);
+    }
+
+    public SimulatedRadioControl getSimulatedRadioControl() {
+        return mActivePhone.getSimulatedRadioControl();
+    }
+
+    public boolean enableDataConnectivity() {
+        return mActivePhone.enableDataConnectivity();
+    }
+
+    public boolean disableDataConnectivity() {
+        return mActivePhone.disableDataConnectivity();
+    }
+
+    public int enableApnType(String type) {
+        return mActivePhone.enableApnType(type);
+    }
+
+    public int disableApnType(String type) {
+        return mActivePhone.disableApnType(type);
+    }
+
+    public boolean isDataConnectivityPossible() {
+        return mActivePhone.isDataConnectivityPossible();
+    }
+
+    public String getInterfaceName(String apnType) {
+        return mActivePhone.getInterfaceName(apnType);
+    }
+
+    public String getIpAddress(String apnType) {
+        return mActivePhone.getIpAddress(apnType);
+    }
+
+    public String getGateway(String apnType) {
+        return mActivePhone.getGateway(apnType);
+    }
+
+    public String[] getDnsServers(String apnType) {
+        return mActivePhone.getDnsServers(apnType);
+    }
+
+    public String getDeviceId() {
+        return mActivePhone.getDeviceId();
+    }
+
+    public String getDeviceSvn() {
+        return mActivePhone.getDeviceSvn();
+    }
+
+    public String getSubscriberId() {
+        return mActivePhone.getSubscriberId();
+    }
+
+    public String getIccSerialNumber() {
+        return mActivePhone.getIccSerialNumber();
+    }
+
+    public String getEsn() {
+        return mActivePhone.getEsn();
+    }
+
+    public String getMeid() {
+        return mActivePhone.getMeid();
+    }
+
+    public PhoneSubInfo getPhoneSubInfo(){
+        return mActivePhone.getPhoneSubInfo();
+    }
+
+    public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+        return mActivePhone.getIccSmsInterfaceManager();
+    }
+
+    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+        return mActivePhone.getIccPhoneBookInterfaceManager();
+    }
+
+    public void setTTYModeEnabled(boolean enable, Message onComplete) {
+        mActivePhone.setTTYModeEnabled(enable, onComplete);
+    }
+
+    public void queryTTYModeEnabled(Message onComplete) {
+        mActivePhone.queryTTYModeEnabled(onComplete);
+    }
+
+    public void activateCellBroadcastSms(int activate, Message response) {
+        mActivePhone.activateCellBroadcastSms(activate, response);
+    }
+
+    public void getCellBroadcastSmsConfig(Message response) {
+        mActivePhone.getCellBroadcastSmsConfig(response);
+    }
+
+    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
+        mActivePhone.setCellBroadcastSmsConfig(configValuesArray, response);
+    }
+
+    public void notifyDataActivity() {
+         mActivePhone.notifyDataActivity();
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
index 61d4c9f..fd822cd 100644
--- a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
+++ b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
@@ -32,11 +32,11 @@
  *
  *      Use android.telephony.TelephonyManager and PhoneStateListener instead.
  *
- * 
+ *
  */
 @Deprecated
 public final class PhoneStateIntentReceiver extends BroadcastReceiver {
-    private static final String LOG_TAG = "PhoneStateIntRecv";
+    private static final String LOG_TAG = "PHONE";
     private static final boolean DBG = false;
 
     public static final String INTENT_KEY_ASU = "asu";
@@ -182,7 +182,7 @@
             if (TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED.equals(action)) {
                 mAsu = intent.getIntExtra(INTENT_KEY_ASU, mAsu);
                 if (DBG) Log.d(LOG_TAG, "onReceiveIntent: set asu=" + mAsu);
-                
+
                 if (mTarget != null && getNotifySignalStrength()) {
                     Message message = Message.obtain(mTarget, mAsuEventWhat);
                     mTarget.sendMessage(message);
diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
index 644d1f4..4d1f7e5 100644
--- a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
+++ b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
@@ -1,10 +1,25 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.android.internal.telephony;
 
 import android.content.Context;
-import android.os.ServiceManager;
-import com.android.internal.telephony.*;
+import android.util.Log;
 
 public class PhoneSubInfo extends IPhoneSubInfo.Stub {
+    static final String LOG_TAG = "PHONE";
     private Phone mPhone;
     private Context mContext;
     private static final String READ_PHONE_STATE =
@@ -13,10 +28,17 @@
     public PhoneSubInfo(Phone phone) {
         mPhone = phone;
         mContext = phone.getContext();
-        ServiceManager.addService("iphonesubinfo", this);
     }
+
+    public void dispose() {
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "PhoneSubInfo finalized");
+    }
+
     /**
-     * Retrieves the unique device ID, e.g., IMEI for GSM phones.
+     * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
      */
     public String getDeviceId() {
         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
@@ -41,11 +63,11 @@
     }
 
     /**
-     * Retrieves the serial number of the SIM, if applicable.
+     * Retrieves the serial number of the ICC, if applicable.
      */
-    public String getSimSerialNumber() {
+    public String getIccSerialNumber() {
         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
-        return mPhone.getSimSerialNumber();
+        return mPhone.getIccSerialNumber();
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java
new file mode 100644
index 0000000..450b3a7
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.ServiceManager;
+
+
+public class PhoneSubInfoProxy extends IPhoneSubInfo.Stub {
+    private PhoneSubInfo mPhoneSubInfo;
+
+    public PhoneSubInfoProxy(PhoneSubInfo phoneSubInfo) {
+        mPhoneSubInfo = phoneSubInfo;
+        if(ServiceManager.getService("iphonesubinfo") == null) {
+            ServiceManager.addService("iphonesubinfo", this);
+        }
+    }
+
+    public void setmPhoneSubInfo(PhoneSubInfo phoneSubInfo) {
+        this.mPhoneSubInfo = phoneSubInfo;
+    }
+
+    public String getDeviceId() {
+        return mPhoneSubInfo.getDeviceId();
+    }
+
+    public String getDeviceSvn() {
+        return mPhoneSubInfo.getDeviceSvn();
+    }
+
+    /**
+     * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
+     */
+    public String getSubscriberId() {
+        return mPhoneSubInfo.getSubscriberId();
+    }
+
+    /**
+     * Retrieves the serial number of the ICC, if applicable.
+     */
+    public String getIccSerialNumber() {
+        return mPhoneSubInfo.getIccSerialNumber();
+    }
+
+    /**
+     * Retrieves the phone number string for line 1.
+     */
+    public String getLine1Number() {
+        return mPhoneSubInfo.getLine1Number();
+    }
+
+    /**
+     * Retrieves the alpha identifier for line 1.
+     */
+    public String getLine1AlphaTag() {
+        return mPhoneSubInfo.getLine1AlphaTag();
+    }
+
+    /**
+     * Retrieves the voice mail number.
+     */
+    public String getVoiceMailNumber() {
+        return mPhoneSubInfo.getVoiceMailNumber();
+    }
+
+    /**
+     * Retrieves the alpha identifier associated with the voice mail number.
+     */
+    public String getVoiceMailAlphaTag() {
+        return mPhoneSubInfo.getVoiceMailAlphaTag();
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
similarity index 66%
rename from telephony/java/com/android/internal/telephony/gsm/RIL.java
rename to telephony/java/com/android/internal/telephony/RIL.java
index e2d0f72..cebbe5c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import static com.android.internal.telephony.gsm.RILConstants.*;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -32,22 +31,36 @@
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.gsm.SmsManager;
-import android.telephony.gsm.SmsMessage;
 import android.telephony.NeighboringCellInfo;
-import android.util.Config;
+import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
 import android.util.Log;
+import android.util.Config;
 
-import java.io.IOException;
+import static com.android.internal.telephony.RILConstants.*;
+
+import com.android.internal.telephony.CallForwardInfo;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.gsm.NetworkInfo;
+import com.android.internal.telephony.gsm.PDPContextState;
+import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.IccCardApplication;
+import com.android.internal.telephony.IccCardStatus;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.SmsResponse;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
 import java.io.InputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 
 /**
  * {@hide}
  */
-class RILRequest
-{
+class RILRequest {
     static final String LOG_TAG = "RILJ";
 
     //***** Class Variables
@@ -67,14 +80,14 @@
 
     /**
      * Retrieves a new RILRequest instance from the pool.
-     * 
+     *
      * @param request RIL_REQUEST_*
      * @param result sent when operation completes
      * @return a RILRequest instance from the pool.
      */
     static RILRequest obtain(int request, Message result) {
         RILRequest rr = null;
-        
+
         synchronized(sPoolSync) {
             if (sPool != null) {
                 rr = sPool;
@@ -83,7 +96,7 @@
                 sPoolSize--;
             }
         }
-        
+
         if (rr == null) {
             rr = new RILRequest();
         }
@@ -108,7 +121,7 @@
 
     /**
      * Returns a RILRequest instance to the pool.
-     * 
+     *
      * Note: This should only be called once per use.
      */
     void release() {
@@ -121,21 +134,18 @@
         }
     }
 
-    private RILRequest()
-    {
+    private RILRequest() {
     }
 
     static void
-    resetSerial()
-    {
+    resetSerial() {
         synchronized(sSerialMonitor) {
             sNextSerial = 0;
         }
     }
 
     String
-    serialString()
-    {
+    serialString() {
         //Cheesy way to do %04d
         StringBuilder sb = new StringBuilder(8);
         String sn;
@@ -154,14 +164,13 @@
     }
 
     void
-    onError(int error)
-    {
+    onError(int error) {
         CommandException ex;
 
         ex = CommandException.fromRilErrno(error);
 
         if (RIL.RILJ_LOGD) Log.d(LOG_TAG, serialString() + "< "
-            + RIL.requestToString(mRequest) 
+            + RIL.requestToString(mRequest)
             + " error: " + ex);
 
         if (mResult != null) {
@@ -180,11 +189,10 @@
 /**
  * RIL implementation of the CommandsInterface.
  * FIXME public only for testing
- * 
+ *
  * {@hide}
  */
-public final class RIL extends BaseCommands implements CommandsInterface
-{
+public final class RIL extends BaseCommands implements CommandsInterface {
     static final String LOG_TAG = "RILJ";
     private static final boolean DBG = false;
     static final boolean RILJ_LOGD = Config.LOGD;
@@ -194,20 +202,20 @@
     //***** Instance Variables
 
     LocalSocket mSocket;
-    HandlerThread mSenderThread;    
+    HandlerThread mSenderThread;
     RILSender mSender;
     Thread mReceiverThread;
     RILReceiver mReceiver;
     private Context mContext;
     WakeLock mWakeLock;
     int mRequestMessagesPending;
-    
+
     // Is this the first radio state change?
     private boolean mInitialRadioStateChange = true;
 
     //I'd rather this be LinkedList or something
     ArrayList<RILRequest> mRequestsList = new ArrayList<RILRequest>();
-    
+
     Object     mLastNITZTimeInfo;
 
     //***** Events
@@ -226,6 +234,11 @@
 
     static final int SOCKET_OPEN_RETRY_MILLIS = 4 * 1000;
 
+    // The number of the required config values for broadcast SMS stored in the C struct
+    // RIL_CDMA_BroadcastServiceInfo
+    private static final int CDMA_BSI_NO_OF_INTS_STRUCT = 3;
+
+    private static final int CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES = 31;
 
     BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
@@ -238,20 +251,18 @@
             }
         }
     };
-    
-    class RILSender extends Handler implements Runnable
-    {
+
+    class RILSender extends Handler implements Runnable {
         public RILSender(Looper looper) {
             super(looper);
         }
-        
+
         // Only allocated once
         byte[] dataLength = new byte[4];
 
         //***** Runnable implementation
         public void
-        run()
-        {
+        run() {
             //setup if needed
         }
 
@@ -259,11 +270,10 @@
         //***** Handler implemementation
 
         public void
-        handleMessage(Message msg)
-        {
+        handleMessage(Message msg) {
             RILRequest rr = (RILRequest)(msg.obj);
             RILRequest req = null;
-            
+
             switch (msg.what) {
                 case EVENT_SEND:
                     /**
@@ -300,7 +310,7 @@
 
                         if (data.length > RIL_MAX_COMMAND_BYTES) {
                             throw new RuntimeException(
-                                    "Parcel larger than max bytes allowed! " 
+                                    "Parcel larger than max bytes allowed! "
                                                           + data.length);
                         }
 
@@ -311,7 +321,7 @@
 
                         //Log.v(LOG_TAG, "writing packet: " + data.length + " bytes");
 
-                        s.getOutputStream().write(dataLength);                    
+                        s.getOutputStream().write(dataLength);
                         s.getOutputStream().write(data);
                     } catch (IOException ex) {
                         Log.e(LOG_TAG, "IOException", ex);
@@ -351,12 +361,12 @@
                                     Log.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " +
                                         " mReqPending=" + mRequestMessagesPending +
                                         " mRequestList=" + count);
-    
+
                                     for (int i = 0; i < count; i++) {
                                         rr = mRequestsList.get(i);
                                         Log.d(LOG_TAG, i + ": [" + rr.mSerial + "] " +
                                             requestToString(rr.mRequest));
-                                            
+
                                     }
                                 }
                             }
@@ -383,8 +393,7 @@
      * @throws IOException
      */
     private static int readRilMessage(InputStream is, byte[] buffer)
-            throws IOException
-    {
+            throws IOException {
         int countRead;
         int offset;
         int remaining;
@@ -429,20 +438,17 @@
         return messageLength;
     }
 
-    class RILReceiver implements Runnable
-    {
+    class RILReceiver implements Runnable {
         byte[] buffer;
 
-        RILReceiver()
-        {
+        RILReceiver() {
             buffer = new byte[RIL_MAX_COMMAND_BYTES];
         }
 
         public void
-        run()
-        {
+        run() {
             int retryCount = 0;
-            
+
             try {for (;;) {
                 LocalSocket s = null;
                 LocalSocketAddress l;
@@ -460,23 +466,23 @@
                     } catch (IOException ex2) {
                         //ignore failure to close after failure to connect
                     }
-                
+
                     // don't print an error message after the the first time
                     // or after the 8th time
 
                     if (retryCount == 8) {
-                        Log.e (LOG_TAG, 
+                        Log.e (LOG_TAG,
                             "Couldn't find '" + SOCKET_NAME_RIL
                             + "' socket after " + retryCount
                             + " times, continuing to retry silently");
                     } else if (retryCount > 0 && retryCount < 8) {
-                        Log.i (LOG_TAG, 
+                        Log.i (LOG_TAG,
                             "Couldn't find '" + SOCKET_NAME_RIL
                             + "' socket; retrying after timeout");
                     }
 
                     try {
-                        Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);                 
+                        Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
                     } catch (InterruptedException er) {
                     }
 
@@ -492,7 +498,7 @@
                 int length = 0;
                 try {
                     InputStream is = mSocket.getInputStream();
-                
+
                     for (;;) {
                         Parcel p;
 
@@ -524,9 +530,9 @@
                       + "' socket");
 
                 setRadioState (RadioState.RADIO_UNAVAILABLE);
-                
+
                 try {
-                    mSocket.close();                    
+                    mSocket.close();
                 } catch (IOException ex) {
                 }
 
@@ -551,15 +557,35 @@
 
 
 
-    //***** Constructor
-
+    //***** Constructors
     public
-    RIL(Context context)
-    {
+    RIL(Context context) {
+        this(context, RILConstants.PREFERRED_NETWORK_MODE,
+                RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
+    }
+
+    public RIL(Context context, int networkMode, int cdmaSubscription) {
         super(context);
+        mCdmaSubscription  = cdmaSubscription;
+        mNetworkMode = networkMode;
+        //At startup mPhoneType is first set from networkMode
+        switch(networkMode) {
+            case RILConstants.NETWORK_MODE_CDMA:
+            case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+            case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+            case RILConstants.NETWORK_MODE_GLOBAL:
+                mPhoneType = RILConstants.CDMA_PHONE;
+                break;
+            case RILConstants.NETWORK_MODE_WCDMA_PREF:
+            case RILConstants.NETWORK_MODE_GSM_ONLY:
+            case RILConstants.NETWORK_MODE_WCDMA_ONLY:
+            case RILConstants.NETWORK_MODE_GSM_UMTS:
+            default:
+                mPhoneType = RILConstants.GSM_PHONE;
+        }
 
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG); 
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
         mWakeLock.setReferenceCounted(false);
         mRequestMessagesPending = 0;
 
@@ -583,9 +609,8 @@
 
     //***** CommandsInterface implementation
 
-    @Override public void 
-    setOnNITZTime(Handler h, int what, Object obj)
-    {
+    @Override public void
+    setOnNITZTime(Handler h, int what, Object obj) {
         super.setOnNITZTime(h, what, obj);
 
         // Send the last NITZ time if we have it
@@ -597,9 +622,10 @@
         }
     }
 
-    public void 
-    getSimStatus(Message result)
-    {
+    public void
+    getIccStatus(Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SIM_STATUS, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -607,9 +633,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPin(String pin, Message result)
-    {
+    public void
+    supplyIccPin(String pin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PIN, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -620,9 +647,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPuk(String puk, String newPin, Message result)
-    {
+    public void
+    supplyIccPuk(String puk, String newPin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PUK, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -634,9 +662,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPin2(String pin, Message result)
-    {
+    public void
+    supplyIccPin2(String pin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PIN2, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -647,9 +676,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPuk2(String puk, String newPin2, Message result)
-    {
+    public void
+    supplyIccPuk2(String puk, String newPin2, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PUK2, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -662,8 +692,9 @@
     }
 
     public void
-    changeSimPin(String oldPin, String newPin, Message result)
-    {
+    changeIccPin(String oldPin, String newPin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -676,8 +707,9 @@
     }
 
     public void
-    changeSimPin2(String oldPin2, String newPin2, Message result)
-    {
+    changeIccPin2(String oldPin2, String newPin2, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN2, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -690,8 +722,7 @@
     }
 
     public void
-    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result)
-    {
+    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_BARRING_PASSWORD, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -704,9 +735,8 @@
         send(rr);
     }
 
-    public void 
-    supplyNetworkDepersonalization(String netpin, Message result)
-    {
+    public void
+    supplyNetworkDepersonalization(String netpin, Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -716,10 +746,9 @@
 
         send(rr);
     }
-    
-    public void 
-    getCurrentCalls (Message result)
-    {
+
+    public void
+    getCurrentCalls (Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -727,19 +756,22 @@
         send(rr);
     }
 
-    public void 
-    getPDPContextList(Message result)
-    {
-        RILRequest rr = RILRequest.obtain(RIL_REQUEST_PDP_CONTEXT_LIST, result);
+    public void
+    getPDPContextList(Message result) {
+        getDataCallList(result);
+    }
+
+    public void
+    getDataCallList(Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_DATA_CALL_LIST, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
         send(rr);
     }
 
-    public void 
-    dial (String address, int clirMode, Message result)
-    {
+    public void
+    dial (String address, int clirMode, Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
 
         rr.mp.writeString(address);
@@ -750,19 +782,20 @@
         send(rr);
     }
 
-    public void 
-    getIMSI(Message result)
-    {
+    public void
+    getIMSI(Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> getIMSI:RIL_REQUEST_GET_IMSI " + RIL_REQUEST_GET_IMSI + " " + requestToString(rr.mRequest));
+        if (RILJ_LOGD) riljLog(rr.serialString() +
+                              "> getIMSI:RIL_REQUEST_GET_IMSI " +
+                              RIL_REQUEST_GET_IMSI +
+                              " " + requestToString(rr.mRequest));
 
         send(rr);
     }
 
     public void
-    getIMEI(Message result)
-    {
+    getIMEI(Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEI, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -771,8 +804,7 @@
     }
 
     public void
-    getIMEISV(Message result)
-    {
+    getIMEISV(Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEISV, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -781,14 +813,14 @@
     }
 
 
-    public void 
-    hangupConnection (int gsmIndex, Message result)
-    {
+    public void
+    hangupConnection (int gsmIndex, Message result) {
         if (RILJ_LOGD) riljLog("hangupConnection: gsmIndex=" + gsmIndex);
 
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP, result);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + gsmIndex);
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " +
+                gsmIndex);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(gsmIndex);
@@ -796,10 +828,9 @@
         send(rr);
     }
 
-    public void 
-    hangupWaitingOrBackground (Message result)
-    {
-        RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, 
+    public void
+    hangupWaitingOrBackground (Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
                                         result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -808,11 +839,10 @@
     }
 
     public void
-    hangupForegroundResumeBackground (Message result)
-    {
-        RILRequest rr 
+    hangupForegroundResumeBackground (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(
-                        RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, 
+                        RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
                                         result);
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
@@ -820,11 +850,10 @@
     }
 
     public void
-    switchWaitingOrHoldingAndActive (Message result)
-    {
-        RILRequest rr 
+    switchWaitingOrHoldingAndActive (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(
-                        RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, 
+                        RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
                                         result);
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
@@ -832,9 +861,8 @@
     }
 
     public void
-    conference (Message result)
-    {
-        RILRequest rr 
+    conference (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_CONFERENCE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -843,10 +871,25 @@
     }
 
 
+    public void setPreferredVoicePrivacy(boolean enable, Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE,
+                result);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(enable ? 1:0);
+
+        send(rr);
+    }
+
+    public void getPreferredVoicePrivacy(Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE,
+                result);
+        send(rr);
+    }
+
     public void
-    separateConnection (int gsmIndex, Message result)
-    {
-        RILRequest rr 
+    separateConnection (int gsmIndex, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SEPARATE_CONNECTION, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -859,9 +902,8 @@
     }
 
     public void
-    acceptCall (Message result)
-    {
-        RILRequest rr 
+    acceptCall (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_ANSWER, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -869,10 +911,9 @@
         send(rr);
     }
 
-    public void 
-    rejectCall (Message result)
-    {
-        RILRequest rr 
+    public void
+    rejectCall (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_UDUB, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -881,8 +922,7 @@
     }
 
     public void
-    explicitCallTransfer (Message result)
-    {
+    explicitCallTransfer (Message result) {
         RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_EXPLICIT_CALL_TRANSFER, result);
 
@@ -892,9 +932,8 @@
     }
 
     public void
-    getLastCallFailCause (Message result)
-    {
-        RILRequest rr 
+    getLastCallFailCause (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -902,11 +941,21 @@
         send(rr);
     }
 
-    public void 
-    getLastPdpFailCause (Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_LAST_PDP_FAIL_CAUSE, result);
+    /**
+     * @deprecated
+     */
+    public void
+    getLastPdpFailCause (Message result) {
+        getLastDataCallFailCause (result);
+    }
+
+    /**
+     * The preferred new alternative to getLastPdpFailCause
+     */
+    public void
+    getLastDataCallFailCause (Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
@@ -914,9 +963,8 @@
     }
 
     public void
-    setMute (boolean enableMute, Message response)
-    {
-        RILRequest rr 
+    setMute (boolean enableMute, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_MUTE, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -929,9 +977,8 @@
     }
 
     public void
-    getMute (Message response)
-    {
-        RILRequest rr 
+    getMute (Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_GET_MUTE, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -940,9 +987,8 @@
     }
 
     public void
-    getSignalStrength (Message result)
-    {
-        RILRequest rr 
+    getSignalStrength (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -950,10 +996,9 @@
         send(rr);
     }
 
-    public void 
-    getRegistrationState (Message result)
-    {
-        RILRequest rr 
+    public void
+    getRegistrationState (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_REGISTRATION_STATE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -961,10 +1006,9 @@
         send(rr);
     }
 
-    public void 
-    getGPRSRegistrationState (Message result)
-    {
-        RILRequest rr 
+    public void
+    getGPRSRegistrationState (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_GPRS_REGISTRATION_STATE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -972,10 +1016,9 @@
         send(rr);
     }
 
-    public void 
-    getOperator(Message result)
-    {
-        RILRequest rr 
+    public void
+    getOperator(Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_OPERATOR, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -983,14 +1026,13 @@
         send(rr);
     }
 
-    public void 
-    sendDtmf(char c, Message result)
-    {
-        RILRequest rr 
+    public void
+    sendDtmf(char c, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_DTMF, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         rr.mp.writeString(Character.toString(c));
 
         send(rr);
@@ -1020,9 +1062,8 @@
 
 
     public void
-    sendSMS (String smscPDU, String pdu, Message result)
-    {
-        RILRequest rr 
+    sendSMS (String smscPDU, String pdu, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);
 
         rr.mp.writeInt(2);
@@ -1030,19 +1071,82 @@
         rr.mp.writeString(pdu);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
+        send(rr);
+    }
+
+    public void
+    sendCdmaSms(byte[] pdu, Message result) {
+        int address_nbr_of_digits;
+        int subaddr_nbr_of_digits;
+        int bearerDataLength;
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(bais);
+
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_CDMA_SEND_SMS, result);
+
+        try {
+            rr.mp.writeInt(dis.readInt()); //teleServiceId
+            rr.mp.writeByte((byte) dis.readInt()); //servicePresent
+            rr.mp.writeInt(dis.readInt()); //serviceCategory
+            rr.mp.writeInt(dis.read()); //address_digit_mode
+            rr.mp.writeInt(dis.read()); //address_nbr_mode
+            rr.mp.writeInt(dis.read()); //address_ton
+            rr.mp.writeInt(dis.read()); //address_nbr_plan
+            address_nbr_of_digits = (byte) dis.read();
+            rr.mp.writeByte((byte) address_nbr_of_digits);
+            for(int i=0; i < address_nbr_of_digits; i++){
+                rr.mp.writeByte(dis.readByte()); // address_orig_bytes[i]
+            }
+            rr.mp.writeInt(dis.read()); //subaddressType
+            rr.mp.writeByte((byte) dis.read()); //subaddr_odd
+            subaddr_nbr_of_digits = (byte) dis.read();
+            rr.mp.writeByte((byte) subaddr_nbr_of_digits);
+            for(int i=0; i < subaddr_nbr_of_digits; i++){
+                rr.mp.writeByte(dis.readByte()); //subaddr_orig_bytes[i]
+            }
+
+            bearerDataLength = dis.read();
+            rr.mp.writeInt(bearerDataLength);
+            for(int i=0; i < bearerDataLength; i++){
+                rr.mp.writeByte(dis.readByte()); //bearerData[i]
+            }
+        }catch (IOException ex){
+            if (RILJ_LOGD) riljLog("sendSmsCdma: conversion from input stream to object failed: "
+                    + ex);
+        }
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
         send(rr);
     }
 
     public void deleteSmsOnSim(int index, Message response) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_DELETE_SMS_ON_SIM,
                 response);
-        
+
         rr.mp.writeInt(1);
         rr.mp.writeInt(index);
 
-        if (RILJ_LOGD) {
-          riljLog(rr.serialString() + "> "
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+                    + requestToString(rr.mRequest)
+                    + " " + index);
+        }
+
+        send(rr);
+    }
+
+    public void deleteSmsOnRuim(int index, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM,
+                response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(index);
+
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                     + requestToString(rr.mRequest)
                     + " " + index);
         }
@@ -1052,17 +1156,35 @@
 
     public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
         status = translateStatus(status);
-        
+
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_WRITE_SMS_TO_SIM,
                 response);
-        
+
         rr.mp.writeInt(status);
         rr.mp.writeString(pdu);
         rr.mp.writeString(smsc);
-        
-        if (RILJ_LOGD) {
-          riljLog(rr.serialString() + "> "
-                    + requestToString(rr.mRequest)  
+
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+                    + requestToString(rr.mRequest)
+                    + " " + status);
+        }
+
+        send(rr);
+    }
+
+    public void writeSmsToRuim(int status, String pdu, Message response) {
+        status = translateStatus(status);
+
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM,
+                response);
+
+        rr.mp.writeInt(status);
+        rr.mp.writeString(pdu);
+
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+                    + requestToString(rr.mRequest)
                     + " " + status);
         }
 
@@ -1075,101 +1197,166 @@
      */
     private int translateStatus(int status) {
         switch(status & 0x7) {
-            case SmsManager.STATUS_ON_SIM_READ:
+            case SmsManager.STATUS_ON_ICC_READ:
                 return 1;
-            case SmsManager.STATUS_ON_SIM_UNREAD:
+            case SmsManager.STATUS_ON_ICC_UNREAD:
                 return 0;
-            case SmsManager.STATUS_ON_SIM_SENT:
+            case SmsManager.STATUS_ON_ICC_SENT:
                 return 3;
-            case SmsManager.STATUS_ON_SIM_UNSENT:
+            case SmsManager.STATUS_ON_ICC_UNSENT:
                 return 2;
         }
-        
+
         // Default to READ.
         return 1;
     }
 
-    public void 
-    setupDefaultPDP(String apn, String user, String password, Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_SETUP_DEFAULT_PDP, result);
+    /**
+     * @deprecated
+     */
+    public void
+    setupDefaultPDP(String apn, String user, String password, Message result) {
+        String radioTechnology = "1"; //0 for CDMA, 1 for GSM/UMTS
+        String profile = ""; //profile number, NULL for GSM/UMTS
+        setupDataCall(radioTechnology, profile, apn, user,
+                password, result);
 
-        rr.mp.writeInt(3);
+    }
+
+    /**
+     * @deprecated
+     */
+    public void
+    deactivateDefaultPDP(int cid, Message result) {
+        deactivateDataCall(cid, result);
+    }
+
+    /**
+     * The preferred new alternative to setupDefaultPDP that is
+     * CDMA-compatible.
+     *
+     */
+    public void
+    setupDataCall(String radioTechnology, String profile, String apn,
+            String user, String password, Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
+
+        rr.mp.writeInt(5);
+
+        rr.mp.writeString(radioTechnology);
+        rr.mp.writeString(profile);
         rr.mp.writeString(apn);
         rr.mp.writeString(user);
         rr.mp.writeString(password);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " "
                 + apn);
-        
+
         send(rr);
     }
 
     public void
-    deactivateDefaultPDP(int cid, Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_DEACTIVATE_DEFAULT_PDP, result);
+    deactivateDataCall(int cid, Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_DEACTIVATE_DATA_CALL, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeString(Integer.toString(cid));
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + cid);
-        
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " +
+                requestToString(rr.mRequest) + " " + cid);
+
         send(rr);
     }
 
     public void
-    setRadioPower(boolean on, Message result)
-    {
-        RILRequest rr 
+    setRadioPower(boolean on, Message result) {
+        //if radio is OFF set preferred NW type and cmda subscription
+        if(mInitialRadioStateChange) {
+            synchronized (mStateMonitor) {
+                if (!mState.isOn()) {
+                    RILRequest rrPnt = RILRequest.obtain(
+                                   RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, null);
+
+                    rrPnt.mp.writeInt(1);
+                    rrPnt.mp.writeInt(mNetworkMode);
+                    if (RILJ_LOGD) riljLog(rrPnt.serialString() + "> "
+                        + requestToString(rrPnt.mRequest) + " : " + mNetworkMode);
+
+                    send(rrPnt);
+
+                    RILRequest rrCs = RILRequest.obtain(
+                                   RIL_REQUEST_CDMA_SET_SUBSCRIPTION, null);
+                    rrCs.mp.writeInt(1);
+                    rrCs.mp.writeInt(mCdmaSubscription);
+                    if (RILJ_LOGD) riljLog(rrCs.serialString() + "> "
+                    + requestToString(rrCs.mRequest) + " : " + mCdmaSubscription);
+                    send(rrCs);
+                }
+            }
+        }
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(on ? 1 : 0);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
 
     public void
-    setSuppServiceNotifications(boolean enable, Message result)
-    {
-        RILRequest rr 
+    setSuppServiceNotifications(boolean enable, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(enable ? 1 : 0);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> "
-                    + requestToString(rr.mRequest));
+                + requestToString(rr.mRequest));
 
         send(rr);
     }
 
-    public void 
-    acknowledgeLastIncomingSMS(boolean success, Message result)
-    {
-        RILRequest rr 
+    public void
+    acknowledgeLastIncomingSMS(boolean success, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SMS_ACKNOWLEDGE, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(success ? 1 : 0);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
-    
+
     public void
-    simIO (int command, int fileid, String path, int p1, int p2, int p3, 
-            String data, String pin2, Message result)
-    {
-        RILRequest rr 
+    acknowledgeLastIncomingCdmaSms(boolean success, Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, result);
+
+        rr.mp.writeInt(success ? 0 : 1); //RIL_CDMA_SMS_ErrorClass
+        // cause code according to X.S004-550E
+        rr.mp.writeInt(39); //39 means other terminal problem; is not interpreted for success.
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+
+    public void
+    iccIO (int command, int fileid, String path, int p1, int p2, int p3,
+            String data, String pin2, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SIM_IO, result);
-                
+
         rr.mp.writeInt(command);
         rr.mp.writeInt(fileid);
         rr.mp.writeString(path);
@@ -1179,51 +1366,48 @@
         rr.mp.writeString(data);
         rr.mp.writeString(pin2);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> simIO: " + requestToString(rr.mRequest)
-                + " 0x" + Integer.toHexString(command) 
-                + " 0x" + Integer.toHexString(fileid) + " " 
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest)
+                + " 0x" + Integer.toHexString(command)
+                + " 0x" + Integer.toHexString(fileid) + " "
                 + p1 + "," + p2 + "," + p3);
-        
-        send(rr);
-    }
-    
-    public void
-    getCLIR(Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_GET_CLIR, result);
-            
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
 
     public void
-    setCLIR(int clirMode, Message result)
-    {
-        RILRequest rr 
+    getCLIR(Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_GET_CLIR, result);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    setCLIR(int clirMode, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_CLIR, result);
 
         // count ints
         rr.mp.writeInt(1);
 
         rr.mp.writeInt(clirMode);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                     + " " + clirMode);
-        
+
         send(rr);
     }
 
     public void
-    queryCallWaiting(int serviceClass, Message response)
-    {
-        RILRequest rr 
+    queryCallWaiting(int serviceClass, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_QUERY_CALL_WAITING, response);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(serviceClass);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                     + " " + serviceClass);
 
@@ -1231,77 +1415,71 @@
     }
 
     public void
-    setCallWaiting(boolean enable, int serviceClass, Message response)
-    {
-        RILRequest rr 
+    setCallWaiting(boolean enable, int serviceClass, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_CALL_WAITING, response);
-        
+
         rr.mp.writeInt(2);
         rr.mp.writeInt(enable ? 1 : 0);
         rr.mp.writeInt(serviceClass);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                 + " " + enable + ", " + serviceClass);
-        
+
         send(rr);
     }
 
     public void
-    setNetworkSelectionModeAutomatic(Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, 
+    setNetworkSelectionModeAutomatic(Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC,
                                     response);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
 
-    public void 
-    setNetworkSelectionModeManual(String operatorNumeric, Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, 
+    public void
+    setNetworkSelectionModeManual(String operatorNumeric, Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
                                     response);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                     + " " + operatorNumeric);
 
         rr.mp.writeString(operatorNumeric);
-        
-        send(rr);
-    }
 
-    public void 
-    getNetworkSelectionMode(Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, 
-                                    response);
-            
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
-        send(rr);
-    }
-
-    public void 
-    getAvailableNetworks(Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, 
-                                    response);
-            
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
         send(rr);
     }
 
     public void
-    setCallForward(int action, int cfReason, int serviceClass, 
-                String number, int timeSeconds, Message response)
-    {
-        RILRequest rr 
+    getNetworkSelectionMode(Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE,
+                                    response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    getAvailableNetworks(Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS,
+                                    response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    setCallForward(int action, int cfReason, int serviceClass,
+                String number, int timeSeconds, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_CALL_FORWARD, response);
 
         rr.mp.writeInt(action);
@@ -1310,19 +1488,18 @@
         rr.mp.writeInt(PhoneNumberUtils.toaFromString(number));
         rr.mp.writeString(number);
         rr.mp.writeInt (timeSeconds);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-                    + " " + action + " " + cfReason + " " + serviceClass 
+                    + " " + action + " " + cfReason + " " + serviceClass
                     + timeSeconds);
-        
+
         send(rr);
     }
 
     public void
     queryCallForwardStatus(int cfReason, int serviceClass,
-                String number, Message response)
-    {
-        RILRequest rr 
+                String number, Message response) {
+        RILRequest rr
             = RILRequest.obtain(RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, response);
 
         rr.mp.writeInt(2); // 2 is for query action, not in used anyway
@@ -1331,7 +1508,7 @@
         rr.mp.writeInt(PhoneNumberUtils.toaFromString(number));
         rr.mp.writeString(number);
         rr.mp.writeInt (0);
-                                     
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                 + " " + cfReason + " " + serviceClass);
 
@@ -1339,8 +1516,7 @@
     }
 
     public void
-    queryCLIP(Message response)
-    {
+    queryCLIP(Message response) {
         RILRequest rr
             = RILRequest.obtain(RIL_REQUEST_QUERY_CLIP, response);
 
@@ -1351,11 +1527,10 @@
 
 
     public void
-    getBasebandVersion (Message response) 
-    {
-        RILRequest rr 
+    getBasebandVersion (Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_BASEBAND_VERSION, response);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
         send(rr);
@@ -1363,14 +1538,13 @@
 
     public void
     queryFacilityLock (String facility, String password, int serviceClass,
-                            Message response)
-    {
+                            Message response) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_QUERY_FACILITY_LOCK, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
         // count strings
-        rr.mp.writeInt(3);        
+        rr.mp.writeInt(3);
 
         rr.mp.writeString(facility);
         rr.mp.writeString(password);
@@ -1382,8 +1556,7 @@
 
     public void
     setFacilityLock (String facility, boolean lockState, String password,
-                        int serviceClass, Message response)
-    {
+                        int serviceClass, Message response) {
         String lockString;
          RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response);
@@ -1402,11 +1575,10 @@
         send(rr);
 
     }
-                        
+
     public void
-    sendUSSD (String ussdString, Message response)
-    {
-        RILRequest rr 
+    sendUSSD (String ussdString, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SEND_USSD, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -1429,9 +1601,8 @@
     }
 
 
-    public void resetRadio(Message result)
-    {
-        RILRequest rr 
+    public void resetRadio(Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_RESET_RADIO, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -1439,13 +1610,12 @@
         send(rr);
     }
 
-    public void invokeOemRilRequestRaw(byte[] data, Message response)
-    {
-        RILRequest rr 
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_RAW, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-               + "[" + SimUtils.bytesToHexString(data) + "]");
+               + "[" + IccUtils.bytesToHexString(data) + "]");
 
         rr.mp.writeByteArray(data);
 
@@ -1453,9 +1623,8 @@
 
     }
 
-    public void invokeOemRilRequestStrings(String[] strings, Message response)
-    {
-        RILRequest rr 
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_STRINGS, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -1592,29 +1761,27 @@
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_LOCATION_UPDATES, response);
         rr.mp.writeInt(1);
         rr.mp.writeInt(enable ? 1 : 0);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                 + requestToString(rr.mRequest) + ": " + enable);
-        
+
         send(rr);
     }
 
     //***** Private Methods
 
-    private void sendScreenState(boolean on)
-    {
+    private void sendScreenState(boolean on) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_SCREEN_STATE, null);
         rr.mp.writeInt(1);
         rr.mp.writeInt(on ? 1 : 0);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ": " + on);
-        
+
         send(rr);
     }
-    
+
     protected void
-    onRadioAvailable()
-    {
+    onRadioAvailable() {
         // In case screen state was lost (due to process crash),
         // this ensures that the RIL knows the correct screen state.
 
@@ -1633,13 +1800,18 @@
             case 2: newState = RadioState.SIM_NOT_READY; break;
             case 3: newState = RadioState.SIM_LOCKED_OR_ABSENT; break;
             case 4: newState = RadioState.SIM_READY; break;
-            default: 
+            case 5: newState = RadioState.RUIM_NOT_READY; break;
+            case 6: newState = RadioState.RUIM_READY; break;
+            case 7: newState = RadioState.RUIM_LOCKED_OR_ABSENT; break;
+            case 8: newState = RadioState.NV_NOT_READY; break;
+            case 9: newState = RadioState.NV_READY; break;
+
+            default:
                 throw new RuntimeException(
                             "Unrecognized RIL_RadioState: " +state);
         }
 
         if (mInitialRadioStateChange) {
-            mInitialRadioStateChange = false;
             if (newState.isOn()) {
                 /* If this is our first notification, make sure the radio
                  * is powered off.  This gets the radio into a known state,
@@ -1648,12 +1820,15 @@
                  * and/or radio knowing.
                  */
                 if (RILJ_LOGD) Log.d(LOG_TAG, "Radio ON @ init; reset to OFF");
-                setRadioPower(false, null);
-                return;
+                    setRadioPower(false, null);
+            } else {
+                if (DBG) Log.d(LOG_TAG, "Radio OFF @ init");
+                setRadioState(newState);
             }
+            mInitialRadioStateChange = false;
+        } else {
+            setRadioState(newState);
         }
-
-        setRadioState(newState);
     }
 
     /**
@@ -1661,13 +1836,12 @@
      * a) There is outstanding RIL request sent to RIL deamon and no replied
      * b) There is a request waiting to be sent out.
      *
-     * There is a WAKE_LOCK_TIMEOUT to release the lock, though it shouldn't 
+     * There is a WAKE_LOCK_TIMEOUT to release the lock, though it shouldn't
      * happen often.
      */
 
     private void
-    acquireWakeLock()
-    {
+    acquireWakeLock() {
         synchronized (mWakeLock) {
             mWakeLock.acquire();
             mRequestMessagesPending++;
@@ -1679,8 +1853,7 @@
     }
 
     private void
-    releaseWakeLockIfDone()
-    {
+    releaseWakeLockIfDone() {
         synchronized (mWakeLock) {
             if (mWakeLock.isHeld() &&
                 (mRequestMessagesPending == 0) &&
@@ -1692,8 +1865,7 @@
     }
 
     private void
-    send(RILRequest rr)
-    {
+    send(RILRequest rr) {
         Message msg;
 
         msg = mSender.obtainMessage(EVENT_SEND, rr);
@@ -1704,8 +1876,7 @@
     }
 
     private void
-    processResponse (Parcel p)
-    {
+    processResponse (Parcel p) {
         int type;
 
         type = p.readInt();
@@ -1714,15 +1885,12 @@
             processUnsolicited (p);
         } else if (type == RESPONSE_SOLICITED) {
             processSolicited (p);
-        }        
+        }
 
         releaseWakeLockIfDone();
     }
 
-
-    
-    private RILRequest findAndRemoveRequestFromList(int serial)
-    {
+    private RILRequest findAndRemoveRequestFromList(int serial) {
         synchronized (mRequestsList) {
             for (int i = 0, s = mRequestsList.size() ; i < s ; i++) {
                 RILRequest rr = mRequestsList.get(i);
@@ -1738,8 +1906,7 @@
     }
 
     private void
-    processSolicited (Parcel p)
-    {
+    processSolicited (Parcel p) {
         int serial, error;
         boolean found = false;
 
@@ -1751,7 +1918,7 @@
         rr = findAndRemoveRequestFromList(serial);
 
         if (rr == null) {
-            Log.w(LOG_TAG, "Unexpected solicited response! sn: " 
+            Log.w(LOG_TAG, "Unexpected solicited response! sn: "
                             + serial + " error: " + error);
             return;
         }
@@ -1763,14 +1930,14 @@
         }
 
         Object ret;
-        
+
         try {switch (rr.mRequest) {
 /*
  cat libs/telephony/ril_commands.h \
  | egrep "^ *{RIL_" \
  | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: ret = \2(p); break;/'
 */
-            case RIL_REQUEST_GET_SIM_STATUS: ret =  responseSimStatus(p); break;
+            case RIL_REQUEST_GET_SIM_STATUS: ret =  responseIccCardStatus(p); break;
             case RIL_REQUEST_ENTER_SIM_PIN: ret =  responseVoid(p); break;
             case RIL_REQUEST_ENTER_SIM_PUK: ret =  responseVoid(p); break;
             case RIL_REQUEST_ENTER_SIM_PIN2: ret =  responseVoid(p); break;
@@ -1796,8 +1963,8 @@
             case RIL_REQUEST_DTMF: ret =  responseVoid(p); break;
             case RIL_REQUEST_SEND_SMS: ret =  responseSMS(p); break;
             case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret =  responseSMS(p); break;
-            case RIL_REQUEST_SETUP_DEFAULT_PDP: ret =  responseStrings(p); break;
-            case RIL_REQUEST_SIM_IO: ret =  responseSIM_IO(p); break;
+            case RIL_REQUEST_SETUP_DATA_CALL: ret =  responseStrings(p); break;
+            case RIL_REQUEST_SIM_IO: ret =  responseICC_IO(p); break;
             case RIL_REQUEST_SEND_USSD: ret =  responseVoid(p); break;
             case RIL_REQUEST_CANCEL_USSD: ret =  responseVoid(p); break;
             case RIL_REQUEST_GET_CLIR: ret =  responseInts(p); break;
@@ -1810,7 +1977,7 @@
             case RIL_REQUEST_GET_IMEI: ret =  responseString(p); break;
             case RIL_REQUEST_GET_IMEISV: ret =  responseString(p); break;
             case RIL_REQUEST_ANSWER: ret =  responseVoid(p); break;
-            case RIL_REQUEST_DEACTIVATE_DEFAULT_PDP: ret =  responseVoid(p); break;
+            case RIL_REQUEST_DEACTIVATE_DATA_CALL: ret =  responseVoid(p); break;
             case RIL_REQUEST_QUERY_FACILITY_LOCK: ret =  responseInts(p); break;
             case RIL_REQUEST_SET_FACILITY_LOCK: ret =  responseVoid(p); break;
             case RIL_REQUEST_CHANGE_BARRING_PASSWORD: ret =  responseVoid(p); break;
@@ -1822,39 +1989,61 @@
             case RIL_REQUEST_DTMF_STOP: ret =  responseVoid(p); break;
             case RIL_REQUEST_BASEBAND_VERSION: ret =  responseString(p); break;
             case RIL_REQUEST_SEPARATE_CONNECTION: ret =  responseVoid(p); break;
-            case RIL_REQUEST_SET_MUTE: ret =responseVoid(p); break;
-            case RIL_REQUEST_GET_MUTE: ret = responseInts(p); break;
-            case RIL_REQUEST_QUERY_CLIP: ret = responseInts(p); break;
-            case RIL_REQUEST_LAST_PDP_FAIL_CAUSE: ret = responseInts(p); break;
-            case RIL_REQUEST_PDP_CONTEXT_LIST: ret =  responseContextList(p); break;
-            case RIL_REQUEST_RESET_RADIO: ret = responseVoid(p); break;
-            case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRaw(p); break;
-            case RIL_REQUEST_OEM_HOOK_STRINGS: ret = responseStrings(p); break;
+            case RIL_REQUEST_SET_MUTE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_GET_MUTE: ret =  responseInts(p); break;
+            case RIL_REQUEST_QUERY_CLIP: ret =  responseInts(p); break;
+            case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: ret =  responseInts(p); break;
+            case RIL_REQUEST_DATA_CALL_LIST: ret =  responseDataCallList(p); break;
+            case RIL_REQUEST_RESET_RADIO: ret =  responseVoid(p); break;
+            case RIL_REQUEST_OEM_HOOK_RAW: ret =  responseRaw(p); break;
+            case RIL_REQUEST_OEM_HOOK_STRINGS: ret =  responseStrings(p); break;
             case RIL_REQUEST_SCREEN_STATE: ret =  responseVoid(p); break;
-            case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret = responseVoid(p); break;
-            case RIL_REQUEST_WRITE_SMS_TO_SIM: ret = responseInts(p); break;
-            case RIL_REQUEST_DELETE_SMS_ON_SIM: ret = responseVoid(p); break;
-            case RIL_REQUEST_SET_BAND_MODE: ret = responseVoid(p); break;
-            case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret = responseInts(p); break;
-            case RIL_REQUEST_STK_GET_PROFILE: ret = responseString(p); break;
-            case RIL_REQUEST_STK_SET_PROFILE: ret = responseVoid(p); break;
-            case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret = responseString(p); break;
-            case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret = responseVoid(p); break;
-            case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret = responseInts(p); break;
-            case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break;
-            case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break;
-            case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseInts(p); break;
+            case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_WRITE_SMS_TO_SIM: ret =  responseInts(p); break;
+            case RIL_REQUEST_DELETE_SMS_ON_SIM: ret =  responseVoid(p); break;
+            case RIL_REQUEST_SET_BAND_MODE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret =  responseInts(p); break;
+            case RIL_REQUEST_STK_GET_PROFILE: ret =  responseString(p); break;
+            case RIL_REQUEST_STK_SET_PROFILE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret =  responseString(p); break;
+            case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret =  responseInts(p); break;
+            case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret =  responseVoid(p); break;
+            case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret =  responseInts(p); break;
             case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break;
-            case  RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break;
-
+            case RIL_REQUEST_SET_LOCATION_UPDATES: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SET_SUBSCRIPTION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: ret =  responseInts(p); break;
+            case RIL_REQUEST_SET_TTY_MODE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_QUERY_TTY_MODE: ret =  responseInts(p); break;
+            case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: ret =  responseInts(p); break;
+            case RIL_REQUEST_CDMA_FLASH: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_BURST_DTMF: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SEND_SMS: ret =  responseSMS(p); break;
+            case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_GET_BROADCAST_CONFIG: ret =  responseBR_SMS_CNF(p); break;
+            case RIL_REQUEST_SET_BROADCAST_CONFIG: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: ret =  responseCDMA_BR_CNF(p); break;
+            case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: ret =  responseVoid(p); break;
+            case RIL_REQUEST_BROADCAST_ACTIVATION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_VALIDATE_AKEY: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SUBSCRIPTION: ret =  responseStrings(p); break;
+            case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: ret =  responseInts(p); break;
+            case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: ret =  responseVoid(p); break;
+            case RIL_REQUEST_DEVICE_IDENTITY: ret =  responseStrings(p); break;
             default:
-                throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest); 
+                throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
             //break;
         }} catch (Throwable tr) {
             // Exceptions here usually mean invalid RIL responses
-            
-            Log.w(LOG_TAG, rr.serialString() + "< " 
-                    + requestToString(rr.mRequest) + " exception, possible invalid RIL response", tr);
+
+            Log.w(LOG_TAG, rr.serialString() + "< "
+                    + requestToString(rr.mRequest)
+                    + " exception, possible invalid RIL response", tr);
 
             if (rr.mResult != null) {
                 AsyncResult.forMessage(rr.mResult, null, tr);
@@ -1866,18 +2055,17 @@
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
             + " " + retToString(rr.mRequest, ret));
-        
+
         if (rr.mResult != null) {
             AsyncResult.forMessage(rr.mResult, ret, null);
             rr.mResult.sendToTarget();
         }
-        
+
         rr.release();
     }
 
     private String
-    retToString(int req, Object ret)
-    {
+    retToString(int req, Object ret) {
         if (ret == null) return "";
         switch (req) {
             // Don't log these return values, for privacy's sake.
@@ -1938,8 +2126,7 @@
     }
 
     private void
-    processUnsolicited (Parcel p)
-    {
+    processUnsolicited (Parcel p) {
         int response;
         Object ret;
 
@@ -1961,7 +2148,7 @@
             case RIL_UNSOL_ON_USSD: ret =  responseStrings(p); break;
             case RIL_UNSOL_NITZ_TIME_RECEIVED: ret =  responseString(p); break;
             case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseInts(p); break;
-            case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED: ret = responseContextList(p);break;
+            case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break;
             case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break;
             case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break;
             case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break;
@@ -1971,8 +2158,12 @@
             case RIL_UNSOL_SIM_REFRESH: ret =  responseInts(p); break;
             case RIL_UNSOL_CALL_RING: ret =  responseVoid(p); break;
             case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break;
-            default: 
-                throw new RuntimeException("Unrecognized unsol response: " + response); 
+            case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:  ret =  responseVoid(p); break;
+            case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:  ret =  responseCdmaSms(p); break;
+            case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:  ret =  responseString(p); break;
+            case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:  ret =  responseVoid(p); break;
+            default:
+                throw new RuntimeException("Unrecognized unsol response: " + response);
             //break; (implied)
         }} catch (Throwable tr) {
             Log.e(LOG_TAG, "Exception processing unsol response: " + response + 
@@ -1984,7 +2175,7 @@
             case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
                 /* has bonus radio state int */
                 setRadioStateFromRILInt(p.readInt());
-                
+
                 if (RILJ_LOGD) unsljLogMore(response, mState.toString());
             break;
             case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
@@ -2009,7 +2200,7 @@
 
                 SmsMessage sms;
 
-                sms = SmsMessage.newFromCMT(a);                
+                sms = SmsMessage.newFromCMT(a);
                 if (mSMSRegistrant != null) {
                     mSMSRegistrant
                         .notifyRegistrant(new AsyncResult(null, sms, null));
@@ -2041,7 +2232,7 @@
             break;
             case RIL_UNSOL_ON_USSD:
                 String[] resp = (String[])ret;
-                
+
                 if (resp.length < 2) {
                     resp = new String[2];
                     resp[0] = ((String[])ret)[0];
@@ -2053,7 +2244,7 @@
                         new AsyncResult (null, resp, null));
                 }
             break;
-            case RIL_UNSOL_NITZ_TIME_RECEIVED:            
+            case RIL_UNSOL_NITZ_TIME_RECEIVED:
                 if (RILJ_LOGD) unsljLogRet(response, ret);
 
                 // has bonus long containing milliseconds since boot that the NITZ
@@ -2066,7 +2257,7 @@
                 result[1] = Long.valueOf(nitzReceiveTime);
 
                 if (mNITZTimeRegistrant != null) {
-                
+
                     mNITZTimeRegistrant
                         .notifyRegistrant(new AsyncResult (null, result, null));
                 } else {
@@ -2074,22 +2265,21 @@
                     mLastNITZTimeInfo = result;
                 }
             break;
-            
+
             case RIL_UNSOL_SIGNAL_STRENGTH:
                 // Note this is set to "verbose" because it happens
                 // frequently
                 if (RILJ_LOGV) unsljLogvRet(response, ret);
-                
+
                 if (mSignalStrengthRegistrant != null) {
                     mSignalStrengthRegistrant.notifyRegistrant(
                                         new AsyncResult (null, ret, null));
                 }
             break;
-            case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED:
+            case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
                 if (RILJ_LOGD) unsljLogRet(response, ret);
 
-                mPDPRegistrants
-                    .notifyRegistrants(new AsyncResult(null, ret, null));
+                mDataConnectionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
             break;
 
             case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
@@ -2140,21 +2330,21 @@
             case RIL_UNSOL_SIM_SMS_STORAGE_FULL:
                 if (RILJ_LOGD) unsljLog(response);
 
-                if (mSimSmsFullRegistrant != null) {
-                    mSimSmsFullRegistrant.notifyRegistrant();
+                if (mIccSmsFullRegistrant != null) {
+                    mIccSmsFullRegistrant.notifyRegistrant();
                 }
                 break;
 
-            case RIL_UNSOL_SIM_REFRESH: 
+            case RIL_UNSOL_SIM_REFRESH:
                 if (RILJ_LOGD) unsljLogRet(response, ret);
 
-                if (mSimRefreshRegistrant != null) {
-                    mSimRefreshRegistrant.notifyRegistrant(
+                if (mIccRefreshRegistrant != null) {
+                    mIccRefreshRegistrant.notifyRegistrant(
                             new AsyncResult (null, ret, null));
                 }
                 break;
-                
-            case RIL_UNSOL_CALL_RING: 
+
+            case RIL_UNSOL_CALL_RING:
                 if (RILJ_LOGD) unsljLog(response);
                 
                 if (mRingRegistrant != null) {
@@ -2168,12 +2358,40 @@
                     mRestrictedStateRegistrant.notifyRegistrant(
                                         new AsyncResult (null, ret, null));
                 }
+                
+            case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
+                if (mIccStatusChangedRegistrants != null) {
+                    mIccStatusChangedRegistrants.notifyRegistrants();
+                }
+                break;
+
+            case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:
+                SmsMessage sms = (SmsMessage) ret;
+
+                if (mSMSRegistrant != null) {
+                    mSMSRegistrant
+                        .notifyRegistrant(new AsyncResult(null, sms, null));
+                }
+                break;
+
+            case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:
+                // TODO T: waiting for SMS BC feature
+                break;
+
+            case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:
+                if (Config.LOGD) {
+                    if (RILJ_LOGD) riljLog("[UNSL]< RUIM_SMS_STORAGE_FULL");
+                }
+
+                if (mIccSmsFullRegistrant != null) {
+                    mIccSmsFullRegistrant.notifyRegistrant();
+                }
+                break;
         }
     }
 
     private Object
-    responseInts(Parcel p)
-    {
+    responseInts(Parcel p) {
         int numInts;
         int response[];
 
@@ -2190,14 +2408,12 @@
 
 
     private Object
-    responseVoid(Parcel p)
-    {
+    responseVoid(Parcel p) {
         return null;
     }
 
     private Object
-    responseCallForward(Parcel p)
-    {
+    responseCallForward(Parcel p) {
         int numInfos;
         CallForwardInfo infos[];
 
@@ -2220,22 +2436,28 @@
     }
 
     private Object
-    responseSuppServiceNotification(Parcel p)
-    {
+    responseSuppServiceNotification(Parcel p) {
         SuppServiceNotification notification = new SuppServiceNotification();
-        
+
         notification.notificationType = p.readInt();
         notification.code = p.readInt();
         notification.index = p.readInt();
         notification.type = p.readInt();
         notification.number = p.readString();
-        
+
         return notification;
     }
-    
+
     private Object
-    responseString(Parcel p)
-    {
+    responseCdmaSms(Parcel p) {
+        SmsMessage sms;
+        sms = SmsMessage.newFromParcel(p);
+
+        return sms;
+    }
+
+    private Object
+    responseString(Parcel p) {
         String response;
 
         response = p.readString();
@@ -2244,8 +2466,7 @@
     }
 
     private Object
-    responseStrings(Parcel p)
-    {
+    responseStrings(Parcel p) {
         int num;
         String response[];
 
@@ -2259,13 +2480,12 @@
                 response[i] = p.readString();
             }
         }
-        
+
         return response;
     }
 
     private Object
-    responseRaw(Parcel p)
-    {
+    responseRaw(Parcel p) {
         int num;
         byte response[];
 
@@ -2275,8 +2495,7 @@
     }
 
     private Object
-    responseSMS(Parcel p)
-    {
+    responseSMS(Parcel p) {
         int messageRef;
         String ackPDU;
 
@@ -2290,46 +2509,110 @@
 
 
     private Object
-    responseSIM_IO(Parcel p)
-    {
+     responseICC_IO(Parcel p) {
         int sw1, sw2;
         byte data[] = null;
         Message ret;
-        
+
         sw1 = p.readInt();
         sw2 = p.readInt();
 
         String s = p.readString();
 
-        return new SimIoResult(sw1, sw2, s);
+        return new IccIoResult(sw1, sw2, s);
     }
 
     private Object
-    responseSimStatus(Parcel p)
-    {
-        int status;
+    responseIccCardStatus(Parcel p) {
+        RadioState currentRadioState;
+        IccCardApplication ca;
 
-        status = ((int[])responseInts(p))[0];
-        switch (status){
-            case RIL_SIM_ABSENT:    return SimStatus.SIM_ABSENT;
-            case RIL_SIM_NOT_READY: return SimStatus.SIM_NOT_READY;
-            case RIL_SIM_READY:     return SimStatus.SIM_READY;
-            case RIL_SIM_PIN:       return SimStatus.SIM_PIN;
-            case RIL_SIM_PUK:       return SimStatus.SIM_PUK;
-            case RIL_SIM_NETWORK_PERSONALIZATION:   
-                                    return SimStatus.SIM_NETWORK_PERSONALIZATION;
-            default:
-                // Unrecognized SIM status.  Treat it like a missing SIM.
-                Log.e(LOG_TAG, "Unrecognized RIL_REQUEST_GET_SIM_STATUS result: " + status);
-                return SimStatus.SIM_ABSENT;
+        currentRadioState = getRadioState();
+
+        IccCardStatus status = new IccCardStatus();
+        status.card_state                      = status.CardStateFromRILInt(p.readInt());
+        status.universal_pin_state             = status.PinStateFromRILInt(p.readInt());
+        status.gsm_umts_subscription_app_index = p.readInt();
+        status.cdma_subscription_app_index     = p.readInt();
+        status.num_applications                = p.readInt();
+
+        // limit to maximum allowed applications
+        if (status.num_applications > IccCardStatus.CARD_MAX_APPS) {
+            status.num_applications = IccCardStatus.CARD_MAX_APPS;
         }
+
+        for (int i = 0 ; i < status.num_applications ; i++) {
+            ca = new IccCardApplication();
+            ca.app_type       = ca.AppTypeFromRILInt(p.readInt());
+            ca.app_state      = ca.AppStateFromRILInt(p.readInt());
+            ca.perso_substate = ca.PersoSubstateFromRILInt(p.readInt());
+            ca.aid            = p.readString();
+            ca.app_label      = p.readString();
+            ca.pin1_replaced  = p.readInt();
+            ca.pin1           = p.readInt();
+            ca.pin2           = p.readInt();
+            status.application.add(ca);
+        }
+
+        // this is common for all radio technologies
+        if (!status.card_state.isCardPresent()) {
+            return IccStatus.ICC_ABSENT;
+        }
+
+        // check radio technology
+        if( currentRadioState == RadioState.RADIO_OFF         ||
+            currentRadioState == RadioState.RADIO_UNAVAILABLE ||
+            currentRadioState == RadioState.SIM_NOT_READY     ||
+            currentRadioState == RadioState.RUIM_NOT_READY    ||
+            currentRadioState == RadioState.NV_NOT_READY      ||
+            currentRadioState == RadioState.NV_READY            ) {
+            return IccStatus.ICC_NOT_READY;
+        }
+
+        if( currentRadioState == RadioState.SIM_LOCKED_OR_ABSENT  ||
+            currentRadioState == RadioState.SIM_READY             ||
+            currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
+            currentRadioState == RadioState.RUIM_READY) {
+
+            int index;
+
+            // check for CDMA radio technology
+            if (currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
+                currentRadioState == RadioState.RUIM_READY) {
+                index = status.cdma_subscription_app_index;
+            }
+            else {
+                index = status.gsm_umts_subscription_app_index;
+            }
+
+            // check if PIN required
+            if (status.application.get(index).app_state.isPinRequired()) {
+                return IccStatus.ICC_PIN;
+            }
+            if (status.application.get(index).app_state.isPukRequired()) {
+                return IccStatus.ICC_PUK;
+            }
+            if (status.application.get(index).app_state.isSubscriptionPersoEnabled()) {
+                return IccStatus.ICC_NETWORK_PERSONALIZATION;
+            }
+            if (status.application.get(index).app_state.isAppReady()) {
+                return IccStatus.ICC_READY;
+            }
+            if (status.application.get(index).app_state.isAppNotReady()) {
+                return IccStatus.ICC_NOT_READY;
+            }
+            return IccStatus.ICC_NOT_READY;
+        }
+
+        // Unrecognized ICC status. Treat it like a missing ICC.
+        Log.e(LOG_TAG, "Unrecognized RIL_REQUEST_GET_SIM_STATUS result: " + status);
+        return IccStatus.ICC_ABSENT;
     }
 
-
     private Object
-    responseCallList(Parcel p)
-    {
+    responseCallList(Parcel p) {
         int num;
+        int voiceSettings;
         ArrayList<DriverCall> response;
         DriverCall dc;
 
@@ -2338,17 +2621,26 @@
 
         for (int i = 0 ; i < num ; i++) {
             dc = new DriverCall();
-            
+
             dc.state = DriverCall.stateFromCLCC(p.readInt());
             dc.index = p.readInt();
             dc.TOA = p.readInt();
             dc.isMpty = (0 != p.readInt());
             dc.isMT = (0 != p.readInt());
             dc.als = p.readInt();
-            dc.isVoice = (0 == p.readInt()) ? false : true;
+            voiceSettings = p.readInt();
+            dc.isVoice = (0 == voiceSettings) ? false : true;
+
+            //dc.isVoicePrivacy = (0 != p.readInt());
+            int voicePrivacy = p.readInt();
+            dc.isVoicePrivacy = (0 != voicePrivacy);
+
             dc.number = p.readString();
-            dc.numberPresentation = DriverCall.presentationFromCLIP(p.readInt());
-            
+            int np = p.readInt();
+            dc.numberPresentation = DriverCall.presentationFromCLIP(np);
+            dc.name = p.readString();
+            dc.namePresentation = p.readInt();
+
             // Make sure there's a leading + on addresses with a TOA
             // of 145
 
@@ -2356,6 +2648,16 @@
                                     dc.number, dc.TOA);
 
             response.add(dc);
+
+            if ( RILConstants.CDMA_VOICE_PRIVACY == voiceSettings ) {
+                mVoicePrivacyOnRegistrants.notifyRegistrants();
+                Log.d(LOG_TAG, "InCall VoicePrivacy is enabled: " +
+                        Integer.toString(voiceSettings));
+            } else {
+                mVoicePrivacyOffRegistrants.notifyRegistrants();
+                Log.d(LOG_TAG, "InCall VoicePrivacy is disabled: " +
+                        Integer.toString(voiceSettings));
+            }
         }
 
         Collections.sort(response);
@@ -2364,8 +2666,7 @@
     }
 
     private Object
-    responseContextList(Parcel p)
-    {
+    responseDataCallList(Parcel p) {
         int num;
         ArrayList<PDPContextState> response;
 
@@ -2376,7 +2677,7 @@
             PDPContextState pdp = new PDPContextState();
 
             pdp.cid = p.readInt();
-            pdp.active = p.readInt() == 0 ? false : true;
+            pdp.active = p.readInt();
             pdp.type = p.readString();
             pdp.apn = p.readString();
             pdp.address = p.readString();
@@ -2388,14 +2689,13 @@
     }
 
     private Object
-    responseNetworkInfos(Parcel p)
-    {
+    responseNetworkInfos(Parcel p) {
         String strings[] = (String [])responseStrings(p);
         ArrayList<NetworkInfo> ret;
 
         if (strings.length % 4 != 0) {
             throw new RuntimeException(
-                "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got " 
+                "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got "
                 + strings.length + " strings, expected multible of 4");
         }
 
@@ -2409,37 +2709,78 @@
                     strings[i+2],
                     strings[i+3]));
         }
-        
+
         return ret;
     }
 
+   private Object
+   responseCellList(Parcel p) {
+       int num;
+       ArrayList<NeighboringCellInfo> response;
+       NeighboringCellInfo cell;
+
+       num = p.readInt();
+       response = new ArrayList<NeighboringCellInfo>(num);
+
+       for (int i = 0 ; i < num ; i++) {
+           try {
+               int rssi = p.readInt();
+               int cid = Integer.valueOf(p.readString(), 16);
+               cell = new NeighboringCellInfo(rssi, cid);
+               response.add(cell);
+           } catch ( Exception e) {
+           }
+       }
+       
+    return response;
+    }
+
     private Object
-    responseCellList(Parcel p)
-    {
-        int num;
-        ArrayList<NeighboringCellInfo> response;
-        NeighboringCellInfo cell;
+    responseBR_SMS_CNF(Parcel p) {
+        // TODO
+        return null;
+    }
 
-        num = p.readInt();
-        response = new ArrayList<NeighboringCellInfo>(num);
+    private Object
+    responseCDMA_BR_CNF(Parcel p) {
+        int numServiceCategories;
+        int response[];
 
-        for (int i = 0 ; i < num ; i++) {
-            try {
-                int rssi = p.readInt();
-                int cid = Integer.valueOf(p.readString(), 16);
-                cell = new NeighboringCellInfo(rssi, cid);
-                response.add(cell);
-            } catch ( Exception e) {
+        numServiceCategories = p.readInt();
+
+        if (numServiceCategories == 0) {
+            int numInts;
+            numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1;
+            response = new int[numInts];
+
+            // indicate that a zero length table was received
+            response[0] = 0;
+            //for all supported service categories set 'english' as default language
+            //and selection status to false
+            for (int i = 1, j = 1
+                    ; i <= (CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES
+                                * CDMA_BSI_NO_OF_INTS_STRUCT)
+                                        ; i += CDMA_BSI_NO_OF_INTS_STRUCT, j++ ) {
+                response[i] = j;
+                response[i+1] = 1;
+                response[i+2] = 0;
             }
+        } else {
+            int numInts;
+            numInts = numServiceCategories * CDMA_BSI_NO_OF_INTS_STRUCT + 1;
+            response = new int[numInts];
+
+            response[0] = numServiceCategories;
+            for (int i = 1 ; i < numInts; i++) {
+                 response[i] = p.readInt();
+             }
         }
 
         return response;
     }
 
-
     static String
-    requestToString(int request) 
-    {
+    requestToString(int request) {
 /*
  cat libs/telephony/ril_commands.h \
  | egrep "^ *{RIL_" \
@@ -2472,7 +2813,7 @@
             case RIL_REQUEST_DTMF: return "DTMF";
             case RIL_REQUEST_SEND_SMS: return "SEND_SMS";
             case RIL_REQUEST_SEND_SMS_EXPECT_MORE: return "SEND_SMS_EXPECT_MORE";
-            case RIL_REQUEST_SETUP_DEFAULT_PDP: return "SETUP_DEFAULT_PDP";
+            case RIL_REQUEST_SETUP_DATA_CALL: return "SETUP_DATA_CALL";
             case RIL_REQUEST_SIM_IO: return "SIM_IO";
             case RIL_REQUEST_SEND_USSD: return "SEND_USSD";
             case RIL_REQUEST_CANCEL_USSD: return "CANCEL_USSD";
@@ -2486,7 +2827,7 @@
             case RIL_REQUEST_GET_IMEI: return "GET_IMEI";
             case RIL_REQUEST_GET_IMEISV: return "GET_IMEISV";
             case RIL_REQUEST_ANSWER: return "ANSWER";
-            case RIL_REQUEST_DEACTIVATE_DEFAULT_PDP: return "DEACTIVATE_DEFAULT_PDP";
+            case RIL_REQUEST_DEACTIVATE_DATA_CALL: return "DEACTIVATE_DATA_CALL";
             case RIL_REQUEST_QUERY_FACILITY_LOCK: return "QUERY_FACILITY_LOCK";
             case RIL_REQUEST_SET_FACILITY_LOCK: return "SET_FACILITY_LOCK";
             case RIL_REQUEST_CHANGE_BARRING_PASSWORD: return "CHANGE_BARRING_PASSWORD";
@@ -2501,8 +2842,8 @@
             case RIL_REQUEST_SET_MUTE: return "SET_MUTE";
             case RIL_REQUEST_GET_MUTE: return "GET_MUTE";
             case RIL_REQUEST_QUERY_CLIP: return "QUERY_CLIP";
-            case RIL_REQUEST_LAST_PDP_FAIL_CAUSE: return "LAST_PDP_FAIL_CAUSE";
-            case RIL_REQUEST_PDP_CONTEXT_LIST: return "PDP_CONTEXT_LIST";
+            case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: return "LAST_DATA_CALL_FAIL_CAUSE";
+            case RIL_REQUEST_DATA_CALL_LIST: return "DATA_CALL_LIST";
             case RIL_REQUEST_RESET_RADIO: return "RESET_RADIO";
             case RIL_REQUEST_OEM_HOOK_RAW: return "OEM_HOOK_RAW";
             case RIL_REQUEST_OEM_HOOK_STRINGS: return "OEM_HOOK_STRINGS";
@@ -2522,6 +2863,28 @@
             case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: return "REQUEST_GET_PREFERRED_NETWORK_TYPE";
             case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: return "REQUEST_GET_NEIGHBORING_CELL_IDS";
             case RIL_REQUEST_SET_LOCATION_UPDATES: return "REQUEST_SET_LOCATION_UPDATES";
+            case RIL_REQUEST_CDMA_SET_SUBSCRIPTION: return "RIL_REQUEST_CDMA_SET_SUBSCRIPTION";
+            case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: return "RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE";
+            case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: return "RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE";
+            case RIL_REQUEST_SET_TTY_MODE: return "RIL_REQUEST_SET_TTY_MODE";
+            case RIL_REQUEST_QUERY_TTY_MODE: return "RIL_REQUEST_QUERY_TTY_MODE";
+            case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: return "RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE";
+            case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: return "RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE";
+            case RIL_REQUEST_CDMA_FLASH: return "RIL_REQUEST_CDMA_FLASH";
+            case RIL_REQUEST_CDMA_BURST_DTMF: return "RIL_REQUEST_CDMA_BURST_DTMF";
+            case RIL_REQUEST_CDMA_SEND_SMS: return "RIL_REQUEST_CDMA_SEND_SMS";
+            case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: return "RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE";
+            case RIL_REQUEST_GET_BROADCAST_CONFIG: return "RIL_REQUEST_GET_BROADCAST_CONFIG";
+            case RIL_REQUEST_SET_BROADCAST_CONFIG: return "RIL_REQUEST_SET_BROADCAST_CONFIG";
+            case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: return "RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG";
+            case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: return "RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG";
+            case RIL_REQUEST_BROADCAST_ACTIVATION: return "RIL_REQUEST_BROADCAST_ACTIVATION";
+            case RIL_REQUEST_CDMA_VALIDATE_AKEY: return "RIL_REQUEST_CDMA_VALIDATE_AKEY";
+            case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: return "RIL_REQUEST_CDMA_BROADCAST_ACTIVATION";
+            case RIL_REQUEST_CDMA_SUBSCRIPTION: return "RIL_REQUEST_CDMA_SUBSCRIPTION";
+            case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: return "RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM";
+            case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: return "RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM";
+            case RIL_REQUEST_DEVICE_IDENTITY: return "RIL_REQUEST_DEVICE_IDENTITY";
             default: return "<unknown request>";
         }
     }
@@ -2545,7 +2908,7 @@
             case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST";
             case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED";
             case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH";
-            case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED: return "UNSOL_PDP_CONTEXT_LIST_CHANGED";
+            case RIL_UNSOL_DATA_CALL_LIST_CHANGED: return "UNSOL_DATA_CALL_LIST_CHANGED";
             case RIL_UNSOL_SUPP_SVC_NOTIFICATION: return "UNSOL_SUPP_SVC_NOTIFICATION";
             case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END";
             case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND";
@@ -2554,7 +2917,7 @@
             case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FULL";
             case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH";
             case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";
-            case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "RIL_UNSOL_RESTRICTED_STATE_CHANGED";
+            case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "RIL_UNSOL_RESTRICTED_STATE_CHANGED";            
             default: return "<unknown reponse>";
         }
     }
@@ -2583,4 +2946,140 @@
         riljLogv("[UNSL]< " + responseToString(response) + " " + retToString(response, ret));
     }
 
+    
+    // ***** Methods for CDMA support
+    public void
+    getDeviceIdentity(Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_DEVICE_IDENTITY, response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    getCDMASubscription(Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SUBSCRIPTION, response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void setPhoneType(int phoneType) { //Set by CDMAPhone and GSMPhone constructor
+        mPhoneType = phoneType;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void queryCdmaRoamingPreference(Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(cdmaRoamingType);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                + " : " + cdmaRoamingType);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCdmaSubscription(int cdmaSubscription , Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_CDMA_SET_SUBSCRIPTION, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(cdmaSubscription);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                + " : " + cdmaSubscription);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void queryTTYModeEnabled(Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_QUERY_TTY_MODE, response);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setTTYModeEnabled(boolean enable, Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_SET_TTY_MODE, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(enable ? 1 : 0);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void
+    sendCDMAFeatureCode(String FeatureCode, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_FLASH, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeString(FeatureCode);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                + " : " + FeatureCode);
+
+        send(rr);
+    }
+
+    public void getCdmaBroadcastConfig(Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG, response);
+
+        send(rr);
+    }
+
+    public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG, response);
+
+        rr.mp.writeInt(configValuesArray[0]);
+        for(int i = 1; i <= (configValuesArray[0] * 3); i++) {
+            rr.mp.writeInt(configValuesArray[i]);
+        }
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void activateCdmaBroadcastSms(int activate, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BROADCAST_ACTIVATION, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(activate);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
new file mode 100644
index 0000000..9c63627
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+
+/**
+ * {@hide}
+ */
+public interface RILConstants {
+    // From the top of ril.cpp
+    int RIL_ERRNO_INVALID_RESPONSE = -1;
+
+    // from RIL_Errno
+    int SUCCESS = 0;
+    int RADIO_NOT_AVAILABLE = 1;              /* If radio did not start or is resetting */
+    int GENERIC_FAILURE = 2;
+    int PASSWORD_INCORRECT = 3;               /* for PIN/PIN2 methods only! */
+    int SIM_PIN2 = 4;                         /* Operation requires SIM PIN2 to be entered */
+    int SIM_PUK2 = 5;                         /* Operation requires SIM PIN2 to be entered */
+    int REQUEST_NOT_SUPPORTED = 6;
+    int REQUEST_CANCELLED = 7;
+    int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice call in
+                                                 class C */
+    int OP_NOT_ALLOWED_BEFORE_REG_NW = 9;     /* request is not allowed before device registers to
+                                                 network */
+    int SMS_SEND_FAIL_RETRY = 10;             /* send sms fail and need retry */
+
+    /* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
+    int NETWORK_MODE_WCDMA_PREF     = 0; /* GSM/WCDMA (WCDMA preferred) */
+    int NETWORK_MODE_GSM_ONLY       = 1; /* GSM only */
+    int NETWORK_MODE_WCDMA_ONLY     = 2; /* WCDMA only */
+    int NETWORK_MODE_GSM_UMTS       = 3; /* GSM/WCDMA (auto mode, according to PRL)
+                                            AVAILABLE Application Settings menu*/
+    int NETWORK_MODE_CDMA           = 4; /* CDMA and EvDo (auto mode, according to PRL)
+                                            AVAILABLE Application Settings menu*/
+    int NETWORK_MODE_CDMA_NO_EVDO   = 5; /* CDMA only */
+    int NETWORK_MODE_EVDO_NO_CDMA   = 6; /* EvDo only */
+    int NETWORK_MODE_GLOBAL         = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
+                                            AVAILABLE Application Settings menu*/
+    int PREFERRED_NETWORK_MODE      = NETWORK_MODE_GSM_ONLY;
+
+    /* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
+    int SUBSCRIPTION_FROM_RUIM      = 0; /* CDMA subscription from RUIM when available */
+    int SUBSCRIPTION_FROM_NV        = 1; /* CDMA subscription from NV */
+    int PREFERRED_CDMA_SUBSCRIPTION = SUBSCRIPTION_FROM_NV;
+
+    int CDMA_CELL_BROADCAST_SMS_DISABLED = 1;
+    int CDMA_CELL_BROADCAST_SMS_ENABLED  = 0;
+
+    int CDMA_PHONE = 0;
+    int GSM_PHONE = 1;
+
+    int CDM_TTY_MODE_DISABLED = 0;
+    int CDM_TTY_MODE_ENABLED = 1;
+
+    byte CDMA_VOICE_PRIVACY = 0x70;           /* "p" value used in Ril_Call.isVoice if Privacy
+                                                 is active  */
+
+/*
+cat include/telephony/ril.h | \
+   egrep '^#define' | \
+   sed -re 's/^#define +([^ ]+)* +([^ ]+)/    int \1 = \2;/' \
+   >>java/android/com.android.internal.telephony/gsm/RILConstants.java
+*/
+
+
+    int RIL_SIM_ABSENT = 0;
+    int RIL_SIM_NOT_READY = 1;
+    int RIL_SIM_READY = 2;
+    int RIL_SIM_PIN = 3;
+    int RIL_SIM_PUK = 4;
+    int RIL_SIM_NETWORK_PERSONALIZATION = 5;
+
+    /**
+     * No restriction at all including voice/SMS/USSD/SS/AV64
+     * and packet data.
+     */
+    int RIL_RESTRICTED_STATE_NONE = 0x00;
+    /**
+     * Block emergency call due to restriction.
+     * But allow all normal voice/SMS/USSD/SS/AV64.
+     */
+    int RIL_RESTRICTED_STATE_CS_EMERGENCY = 0x01;
+    /**
+     * Block all normal voice/SMS/USSD/SS/AV64 due to restriction.
+     * Only Emergency call allowed.
+     */
+    int RIL_RESTRICTED_STATE_CS_NORMAL = 0x02;
+    /**
+     * Block all voice/SMS/USSD/SS/AV64
+     * including emergency call due to restriction.
+     */
+    int RIL_RESTRICTED_STATE_CS_ALL = 0x04;
+    /**
+     * Block packet data access due to restriction.
+     */
+    int RIL_RESTRICTED_STATE_PS_ALL = 0x10;
+
+    int RIL_REQUEST_GET_SIM_STATUS = 1;
+    int RIL_REQUEST_ENTER_SIM_PIN = 2;
+    int RIL_REQUEST_ENTER_SIM_PUK = 3;
+    int RIL_REQUEST_ENTER_SIM_PIN2 = 4;
+    int RIL_REQUEST_ENTER_SIM_PUK2 = 5;
+    int RIL_REQUEST_CHANGE_SIM_PIN = 6;
+    int RIL_REQUEST_CHANGE_SIM_PIN2 = 7;
+    int RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION = 8;
+    int RIL_REQUEST_GET_CURRENT_CALLS = 9;
+    int RIL_REQUEST_DIAL = 10;
+    int RIL_REQUEST_GET_IMSI = 11;
+    int RIL_REQUEST_HANGUP = 12;
+    int RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND = 13;
+    int RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND = 14;
+    int RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE = 15;
+    int RIL_REQUEST_CONFERENCE = 16;
+    int RIL_REQUEST_UDUB = 17;
+    int RIL_REQUEST_LAST_CALL_FAIL_CAUSE = 18;
+    int RIL_REQUEST_SIGNAL_STRENGTH = 19;
+    int RIL_REQUEST_REGISTRATION_STATE = 20;
+    int RIL_REQUEST_GPRS_REGISTRATION_STATE = 21;
+    int RIL_REQUEST_OPERATOR = 22;
+    int RIL_REQUEST_RADIO_POWER = 23;
+    int RIL_REQUEST_DTMF = 24;
+    int RIL_REQUEST_SEND_SMS = 25;
+    int RIL_REQUEST_SEND_SMS_EXPECT_MORE = 26;
+    int RIL_REQUEST_SETUP_DATA_CALL = 27;
+    int RIL_REQUEST_SIM_IO = 28;
+    int RIL_REQUEST_SEND_USSD = 29;
+    int RIL_REQUEST_CANCEL_USSD = 30;
+    int RIL_REQUEST_GET_CLIR = 31;
+    int RIL_REQUEST_SET_CLIR = 32;
+    int RIL_REQUEST_QUERY_CALL_FORWARD_STATUS = 33;
+    int RIL_REQUEST_SET_CALL_FORWARD = 34;
+    int RIL_REQUEST_QUERY_CALL_WAITING = 35;
+    int RIL_REQUEST_SET_CALL_WAITING = 36;
+    int RIL_REQUEST_SMS_ACKNOWLEDGE = 37;
+    int RIL_REQUEST_GET_IMEI = 38;
+    int RIL_REQUEST_GET_IMEISV = 39;
+    int RIL_REQUEST_ANSWER = 40;
+    int RIL_REQUEST_DEACTIVATE_DATA_CALL = 41;
+    int RIL_REQUEST_QUERY_FACILITY_LOCK = 42;
+    int RIL_REQUEST_SET_FACILITY_LOCK = 43;
+    int RIL_REQUEST_CHANGE_BARRING_PASSWORD = 44;
+    int RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE = 45;
+    int RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC = 46;
+    int RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL = 47;
+    int RIL_REQUEST_QUERY_AVAILABLE_NETWORKS = 48;
+    int RIL_REQUEST_DTMF_START = 49;
+    int RIL_REQUEST_DTMF_STOP = 50;
+    int RIL_REQUEST_BASEBAND_VERSION = 51;
+    int RIL_REQUEST_SEPARATE_CONNECTION = 52;
+    int RIL_REQUEST_SET_MUTE = 53;
+    int RIL_REQUEST_GET_MUTE = 54;
+    int RIL_REQUEST_QUERY_CLIP = 55;
+    int RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE = 56;
+    int RIL_REQUEST_DATA_CALL_LIST = 57;
+    int RIL_REQUEST_RESET_RADIO = 58;
+    int RIL_REQUEST_OEM_HOOK_RAW = 59;
+    int RIL_REQUEST_OEM_HOOK_STRINGS = 60;
+    int RIL_REQUEST_SCREEN_STATE = 61;
+    int RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION = 62;
+    int RIL_REQUEST_WRITE_SMS_TO_SIM = 63;
+    int RIL_REQUEST_DELETE_SMS_ON_SIM = 64;
+    int RIL_REQUEST_SET_BAND_MODE = 65;
+    int RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE = 66;
+    int RIL_REQUEST_STK_GET_PROFILE = 67;
+    int RIL_REQUEST_STK_SET_PROFILE = 68;
+    int RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND = 69;
+    int RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE = 70;
+    int RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM = 71;
+    int RIL_REQUEST_EXPLICIT_CALL_TRANSFER = 72;
+    int RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE = 73;
+    int RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE = 74;
+    int RIL_REQUEST_GET_NEIGHBORING_CELL_IDS = 75;
+    int RIL_REQUEST_SET_LOCATION_UPDATES = 76;
+    int RIL_REQUEST_CDMA_SET_SUBSCRIPTION = 77;
+    int RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE = 78;
+    int RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE = 79;
+    int RIL_REQUEST_SET_TTY_MODE = 80;
+    int RIL_REQUEST_QUERY_TTY_MODE = 81;
+    int RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE = 82;
+    int RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE = 83;
+    int RIL_REQUEST_CDMA_FLASH = 84;
+    int RIL_REQUEST_CDMA_BURST_DTMF = 85;
+    int RIL_REQUEST_CDMA_VALIDATE_AKEY = 86;
+    int RIL_REQUEST_CDMA_SEND_SMS = 87;
+    int RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE = 88;
+    int RIL_REQUEST_GET_BROADCAST_CONFIG = 89;
+    int RIL_REQUEST_SET_BROADCAST_CONFIG = 90;
+    int RIL_REQUEST_BROADCAST_ACTIVATION = 91;
+    int RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG = 92;
+    int RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG = 93;
+    int RIL_REQUEST_CDMA_BROADCAST_ACTIVATION = 94;
+    int RIL_REQUEST_CDMA_SUBSCRIPTION = 95;
+    int RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM = 96;
+    int RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM = 97;
+    int RIL_REQUEST_DEVICE_IDENTITY = 98;
+    int RIL_UNSOL_RESPONSE_BASE = 1000;
+    int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
+    int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
+    int RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED = 1002;
+    int RIL_UNSOL_RESPONSE_NEW_SMS = 1003;
+    int RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT = 1004;
+    int RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM = 1005;
+    int RIL_UNSOL_ON_USSD = 1006;
+    int RIL_UNSOL_ON_USSD_REQUEST = 1007;
+    int RIL_UNSOL_NITZ_TIME_RECEIVED = 1008;
+    int RIL_UNSOL_SIGNAL_STRENGTH = 1009;
+    int RIL_UNSOL_DATA_CALL_LIST_CHANGED = 1010;
+    int RIL_UNSOL_SUPP_SVC_NOTIFICATION = 1011;
+    int RIL_UNSOL_STK_SESSION_END = 1012;
+    int RIL_UNSOL_STK_PROACTIVE_COMMAND = 1013;
+    int RIL_UNSOL_STK_EVENT_NOTIFY = 1014;
+    int RIL_UNSOL_STK_CALL_SETUP = 1015;
+    int RIL_UNSOL_SIM_SMS_STORAGE_FULL = 1016;
+    int RIL_UNSOL_SIM_REFRESH = 1017;
+    int RIL_UNSOL_CALL_RING = 1018;
+    int RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED = 1019;
+    int RIL_UNSOL_RESPONSE_CDMA_NEW_SMS = 1020;
+    int RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS = 1021;
+    int RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL = 1022;
+    int RIL_UNSOL_RESTRICTED_STATE_CHANGED = 1023;
+}
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
new file mode 100644
index 0000000..f2bd361
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.AlertDialog;
+import android.app.PendingIntent.CanceledException;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.net.Uri;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Telephony;
+import android.provider.Telephony.Sms.Intents;
+import android.provider.Settings;
+import android.telephony.SmsMessage;
+import android.telephony.ServiceState;
+import android.util.Config;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsResponse;
+import com.android.internal.telephony.WapPushOverSms;
+import com.android.internal.util.HexDump;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Random;
+
+import com.android.internal.R;
+
+import static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE;
+import static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE;
+import static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU;
+import static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF;
+
+
+public abstract class SMSDispatcher extends Handler {
+    private static final String TAG = "SMS";
+
+    /** Default checking period for SMS sent without user permit */
+    private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000;
+
+    /** Default number of SMS sent in checking period without user permit */
+    private static final int DEFAULT_SMS_MAX_COUNT = 100;
+
+    /** Default timeout for SMS sent query */
+    private static final int DEFAULT_SMS_TIMOUEOUT = 6000;
+
+    protected static final String[] RAW_PROJECTION = new String[] {
+        "pdu",
+        "sequence",
+    };
+
+    static final int MAIL_SEND_SMS = 1;
+
+    static final protected int EVENT_NEW_SMS = 1;
+
+    static final protected int EVENT_SEND_SMS_COMPLETE = 2;
+
+    /** Retry sending a previously failed SMS message */
+    static final protected int EVENT_SEND_RETRY = 3;
+
+    /** Status report received */
+    static final protected int EVENT_NEW_SMS_STATUS_REPORT = 5;
+
+    /** SIM/RUIM storage is full */
+    static final protected int EVENT_ICC_FULL = 6;
+
+    /** SMS confirm required */
+    static final protected int EVENT_POST_ALERT = 7;
+
+    /** Send the user confirmed SMS */
+    static final protected int EVENT_SEND_CONFIRMED_SMS = 8;
+
+    /** Alert is timeout */
+    static final protected int EVENT_ALERT_TIMEOUT = 9;
+
+    protected Phone mPhone;
+    protected Context mContext;
+    protected ContentResolver mResolver;
+    protected CommandsInterface mCm;
+
+    protected final WapPushOverSms mWapPush;
+
+    protected final Uri mRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw");
+
+    /** Maximum number of times to retry sending a failed SMS. */
+    private static final int MAX_SEND_RETRIES = 3;
+    /** Delay before next send attempt on a failed SMS, in milliseconds. */
+    private static final int SEND_RETRY_DELAY = 2000; 
+    /** single part SMS */
+    private static final int SINGLE_PART_SMS = 1;
+
+    /**
+     * Message reference for a CONCATENATED_8_BIT_REFERENCE or
+     * CONCATENATED_16_BIT_REFERENCE message set.  Should be
+     * incremented for each set of concatenated messages.
+     */
+    protected static int sConcatenatedRef;
+
+    private SmsCounter mCounter;
+
+    private SmsTracker mSTracker;
+
+    private static SmsMessage mSmsMessage;
+    private static SmsMessageBase mSmsMessageBase;
+    private SmsMessageBase.SubmitPduBase mSubmitPduBase;
+
+    /**
+     *  Implement the per-application based SMS control, which only allows
+     *  a limit on the number of SMS/MMS messages an app can send in checking
+     *  period.
+     */
+    private class SmsCounter {
+        private int mCheckPeriod;
+        private int mMaxAllowed;
+        private HashMap<String, ArrayList<Long>> mSmsStamp;
+
+        /**
+         * Create SmsCounter
+         * @param mMax is the number of SMS allowed without user permit
+         * @param mPeriod is the checking period
+         */
+        SmsCounter(int mMax, int mPeriod) {
+            mMaxAllowed = mMax;
+            mCheckPeriod = mPeriod;
+            mSmsStamp = new HashMap<String, ArrayList<Long>> ();
+        }
+
+        /**
+         * Check to see if an application allow to send new SMS messages
+         *  
+         * @param appName is the application sending sms
+         * @param smsWaiting is the number of new sms wants to be sent
+         * @return true if application is allowed to send the requested number 
+         *         of new sms messages 
+         */
+        boolean check(String appName, int smsWaiting) {
+            if (!mSmsStamp.containsKey(appName)) {
+                mSmsStamp.put(appName, new ArrayList<Long>());
+            }
+
+            return isUnderLimit(mSmsStamp.get(appName), smsWaiting);
+        }
+
+        private boolean isUnderLimit(ArrayList<Long> sent, int smsWaiting) {
+            Long ct =  System.currentTimeMillis();
+
+            Log.d(TAG, "SMS send size=" + sent.size() + "time=" + ct);
+
+            while (sent.size() > 0 && (ct - sent.get(0)) > mCheckPeriod ) {
+                    sent.remove(0);
+            }
+
+            
+            if ( (sent.size() + smsWaiting) <= mMaxAllowed) {
+                for (int i = 0; i < smsWaiting; i++ ) {
+                    sent.add(ct);
+                }
+                return true;
+            }
+            return false;
+        }
+    }
+
+    protected SMSDispatcher(PhoneBase phone) {
+        mPhone = phone;
+        mWapPush = new WapPushOverSms(phone);
+        mContext = phone.getContext();
+        mResolver = mContext.getContentResolver();
+        mCm = phone.mCM;
+        mSTracker = null;
+
+        int check_period = Settings.Gservices.getInt(mResolver,
+                Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
+                DEFAULT_SMS_CHECK_PERIOD);
+        int max_count = Settings.Gservices.getInt(mResolver,
+                Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
+                DEFAULT_SMS_MAX_COUNT);
+        mCounter = new SmsCounter(max_count, check_period);
+
+        mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
+        mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
+        mCm.setOnIccSmsFull(this, EVENT_ICC_FULL, null);
+
+        // Don't always start message ref at 0.
+        sConcatenatedRef = new Random().nextInt(256);
+    }
+
+    public void dispose() {
+        mCm.unSetOnNewSMS(this);
+        mCm.unSetOnSmsStatus(this);
+        mCm.unSetOnIccSmsFull(this);
+    }
+
+    protected void finalize() {
+        Log.d(TAG, "SMSDispatcher finalized");
+    }
+
+
+    /* TODO: Need to figure out how to keep track of status report routing in a
+     *       persistent manner. If the phone process restarts (reboot or crash),
+     *       we will lose this list and any status reports that come in after
+     *       will be dropped.
+     */
+    /** Sent messages awaiting a delivery status report. */
+    protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>();
+
+    /**
+     * Handles events coming from the phone stack. Overridden from handler.
+     *
+     * @param msg the message to handle
+     */
+    @Override
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+
+        switch (msg.what) {
+        case EVENT_NEW_SMS:
+            // A new SMS has been received by the device
+            if (Config.LOGD) {
+                Log.d(TAG, "New SMS Message Received");
+            }
+
+            SmsMessage sms;
+
+            ar = (AsyncResult) msg.obj;
+
+                // FIXME only acknowledge on store
+            acknowledgeLastIncomingSms(true, null);
+
+            if (ar.exception != null) {
+                Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception);
+                return;
+            }
+
+            sms = (SmsMessage) ar.result;
+            dispatchMessage(sms.mWrappedSmsMessage);
+
+            break;
+
+        case EVENT_SEND_SMS_COMPLETE:
+            // An outbound SMS has been successfully transferred, or failed.
+            handleSendComplete((AsyncResult) msg.obj);
+            break;
+
+        case EVENT_SEND_RETRY:
+            sendSms((SmsTracker) msg.obj);
+            break;
+
+        case EVENT_NEW_SMS_STATUS_REPORT:
+            handleStatusReport((AsyncResult)msg.obj);
+            break;
+
+        case EVENT_ICC_FULL:
+            handleIccFull();
+            break;
+
+        case EVENT_POST_ALERT:
+            handleReachSentLimit((SmsTracker)(msg.obj));
+            break;
+
+        case EVENT_ALERT_TIMEOUT:
+            ((AlertDialog)(msg.obj)).dismiss();
+            msg.obj = null;
+            mSTracker = null;
+            break;
+
+        case EVENT_SEND_CONFIRMED_SMS:
+            if (mSTracker!=null) {
+                if (isMultipartTracker(mSTracker)) {
+                    sendMultipartSms(mSTracker);
+                } else {
+                    sendSms(mSTracker);
+                } 
+                mSTracker = null;
+            }
+            break;
+        }
+    }
+
+    /**
+     * Called when SIM_FULL message is received from the RIL.  Notifies interested
+     * parties that SIM storage for SMS messages is full.
+     */
+    private void handleIccFull(){
+        // broadcast SIM_FULL intent
+        Intent intent = new Intent(Intents.SIM_FULL_ACTION);
+        mPhone.getContext().sendBroadcast(intent, "android.permission.RECEIVE_SMS");
+    }
+
+    /**
+     * Called when a status report is received.  This should correspond to
+     * a previously successful SEND.
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           be a String representing the status report PDU, as ASCII hex.
+     */
+    protected abstract void handleStatusReport(AsyncResult ar);
+
+    /**
+     * Called when SMS send completes. Broadcasts a sentIntent on success.
+     * On failure, either sets up retries or broadcasts a sentIntent with
+     * the failure in the result code.
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           an SmsResponse instance if send was successful.  ar.userObj
+     *           should be an SmsTracker instance.
+     */
+    protected void handleSendComplete(AsyncResult ar) {
+        SmsTracker tracker = (SmsTracker) ar.userObj;
+        PendingIntent sentIntent = tracker.mSentIntent;
+
+        if (ar.exception == null) {
+            if (Config.LOGD) {
+                Log.d(TAG, "SMS send complete. Broadcasting "
+                        + "intent: " + sentIntent);
+            }
+
+            if (tracker.mDeliveryIntent != null) {
+                // Expecting a status report.  Add it to the list.
+                int messageRef = ((SmsResponse)ar.result).messageRef;
+                tracker.mMessageRef = messageRef;
+                deliveryPendingList.add(tracker);
+            }
+
+            if (sentIntent != null) {
+                try {
+                    sentIntent.send(Activity.RESULT_OK);
+                } catch (CanceledException ex) {}
+            }
+        } else {
+            if (Config.LOGD) {
+                Log.d(TAG, "SMS send failed");
+            }
+
+            int ss = mPhone.getServiceState().getState();
+
+            if (ss != ServiceState.STATE_IN_SERVICE) {
+                handleNotInService(ss, tracker);
+            } else if ((((CommandException)(ar.exception)).getCommandError()
+                    == CommandException.Error.SMS_FAIL_RETRY) &&
+                   tracker.mRetryCount < MAX_SEND_RETRIES) {
+                // Retry after a delay if needed.
+                // TODO: According to TS 23.040, 9.2.3.6, we should resend
+                //       with the same TP-MR as the failed message, and
+                //       TP-RD set to 1.  However, we don't have a means of
+                //       knowing the MR for the failed message (EF_SMSstatus
+                //       may or may not have the MR corresponding to this
+                //       message, depending on the failure).  Also, in some
+                //       implementations this retry is handled by the baseband.
+                tracker.mRetryCount++;
+                Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
+                sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
+            } else if (tracker.mSentIntent != null) {
+                // Done retrying; return an error to the app.
+                try {
+                    tracker.mSentIntent.send(RESULT_ERROR_GENERIC_FAILURE);
+                } catch (CanceledException ex) {}
+            }
+        }
+    }
+
+    /**
+     * Handles outbound message when the phone is not in service.
+     *
+     * @param ss     Current service state.  Valid values are:
+     *                  OUT_OF_SERVICE
+     *                  EMERGENCY_ONLY
+     *                  POWER_OFF
+     * @param tracker   An SmsTracker for the current message.
+     */
+    protected void handleNotInService(int ss, SmsTracker tracker) {
+        if (tracker.mSentIntent != null) {
+            try {
+                if (ss == ServiceState.STATE_POWER_OFF) {
+                    tracker.mSentIntent.send(RESULT_ERROR_RADIO_OFF);
+                } else {
+                    tracker.mSentIntent.send(RESULT_ERROR_NO_SERVICE);
+                }
+            } catch (CanceledException ex) {}
+        }
+    }
+
+    /**
+     * Dispatches an incoming SMS messages.
+     *
+     * @param sms the incoming message from the phone
+     */
+    protected abstract void dispatchMessage(SmsMessageBase sms);
+
+
+    /**
+     * If this is the last part send the parts out to the application, otherwise
+     * the part is stored for later processing.
+     */
+    protected void processMessagePart(SmsMessageBase sms, int referenceNumber,
+            int sequence, int count, int destinationPort) {
+        // Lookup all other related parts
+        StringBuilder where = new StringBuilder("reference_number =");
+        where.append(referenceNumber);
+        where.append(" AND address = ?");
+        String[] whereArgs = new String[] {sms.getOriginatingAddress()};
+
+        byte[][] pdus = null;
+        Cursor cursor = null;
+        try {
+            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
+            int cursorCount = cursor.getCount();
+            if (cursorCount != count - 1) {
+                // We don't have all the parts yet, store this one away
+                ContentValues values = new ContentValues();
+                values.put("date", new Long(sms.getTimestampMillis()));
+                values.put("pdu", HexDump.toHexString(sms.getPdu()));
+                values.put("address", sms.getOriginatingAddress());
+                values.put("reference_number", referenceNumber);
+                values.put("count", count);
+                values.put("sequence", sequence);
+                if (destinationPort != -1) {
+                    values.put("destination_port", destinationPort);
+                }
+                mResolver.insert(mRawUri, values);
+
+                return;
+            }
+
+            // All the parts are in place, deal with them
+            int pduColumn = cursor.getColumnIndex("pdu");
+            int sequenceColumn = cursor.getColumnIndex("sequence");
+
+            pdus = new byte[count][];
+            for (int i = 0; i < cursorCount; i++) {
+                cursor.moveToNext();
+                int cursorSequence = (int)cursor.getLong(sequenceColumn);
+                pdus[cursorSequence - 1] = HexDump.hexStringToByteArray(
+                        cursor.getString(pduColumn));
+            }
+            // This one isn't in the DB, so add it
+            pdus[sequence - 1] = sms.getPdu();
+
+            // Remove the parts from the database
+            mResolver.delete(mRawUri, where.toString(), whereArgs);
+        } catch (SQLException e) {
+            Log.e(TAG, "Can't access multipart SMS database", e);
+            return;  // TODO: NACK the message or something, don't just discard.
+        } finally {
+            if (cursor != null) cursor.close();
+        }
+
+        // Dispatch the PDUs to applications
+        switch (destinationPort) {
+        case SmsHeader.PORT_WAP_PUSH: {
+            // Build up the data stream
+            ByteArrayOutputStream output = new ByteArrayOutputStream();
+            for (int i = 0; i < count; i++) {
+                SmsMessage msg = SmsMessage.createFromPdu(pdus[i]);
+                byte[] data = msg.getUserData();
+                output.write(data, 0, data.length);
+            }
+
+            // Handle the PUSH
+            mWapPush.dispatchWapPdu(output.toByteArray());
+            break;
+        }
+
+        case -1:
+            // The messages were not sent to a port
+            dispatchPdus(pdus);
+            break;
+
+        default:
+            // The messages were sent to a port, so concoct a URI for it
+            dispatchPortAddressedPdus(pdus, destinationPort);
+            break;
+        }
+    }
+
+    /**
+     * Dispatches standard PDUs to interested applications
+     *
+     * @param pdus The raw PDUs making up the message
+     */
+    protected void dispatchPdus(byte[][] pdus) {
+        Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
+        intent.putExtra("pdus", pdus);
+        mPhone.getContext().sendBroadcast(
+                intent, "android.permission.RECEIVE_SMS");
+    }
+
+    /**
+     * Dispatches port addressed PDUs to interested applications
+     *
+     * @param pdus The raw PDUs making up the message
+     * @param port The destination port of the messages
+     */
+    protected void dispatchPortAddressedPdus(byte[][] pdus, int port) {
+        Uri uri = Uri.parse("sms://localhost:" + port);
+        Intent intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);
+        intent.putExtra("pdus", pdus);
+        mPhone.getContext().sendBroadcast(
+                intent, "android.permission.RECEIVE_SMS");
+    }
+
+
+    /**
+     * Send a multi-part text based SMS.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     */
+    protected abstract void sendMultipartText(String destinationAddress, String scAddress,
+            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
+            ArrayList<PendingIntent> deliveryIntents);
+
+    /**
+     * Send a SMS
+     *
+     * @param smsc the SMSC to send the message through, or NULL for the
+     *  defatult SMSC
+     * @param pdu the raw PDU to send
+     * @param sentIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        if (pdu == null) {
+            if (sentIntent != null) {
+                try {
+                    sentIntent.send(RESULT_ERROR_NULL_PDU);
+                } catch (CanceledException ex) {}
+            }
+            return;
+        }
+
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        map.put("smsc", smsc);
+        map.put("pdu", pdu);
+
+        SmsTracker tracker = new SmsTracker(map, sentIntent,
+                deliveryIntent);
+        int ss = mPhone.getServiceState().getState();
+
+        if (ss != ServiceState.STATE_IN_SERVICE) {
+            handleNotInService(ss, tracker);
+        } else {
+            String appName = getAppNameByIntent(sentIntent);
+            if (mCounter.check(appName, SINGLE_PART_SMS)) {
+                sendSms(tracker);
+            } else {
+                sendMessage(obtainMessage(EVENT_POST_ALERT, tracker));
+            }
+        }
+    }
+
+    /**
+     * Post an alert while SMS needs user confirm.
+     *
+     * An SmsTracker for the current message.
+     */
+    protected void handleReachSentLimit(SmsTracker tracker) {
+
+        Resources r = Resources.getSystem();
+
+        String appName = getAppNameByIntent(tracker.mSentIntent);
+
+        AlertDialog d = new AlertDialog.Builder(mContext)
+                .setTitle(r.getString(R.string.sms_control_title))
+                .setMessage(appName + " " + r.getString(R.string.sms_control_message))
+                .setPositiveButton(r.getString(R.string.sms_control_yes), mListener)
+                .setNegativeButton(r.getString(R.string.sms_control_no), null)
+                .create();
+
+        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        d.show();
+
+        mSTracker = tracker;
+        sendMessageDelayed ( obtainMessage(EVENT_ALERT_TIMEOUT, d),
+                DEFAULT_SMS_TIMOUEOUT);
+    }
+
+    protected String getAppNameByIntent(PendingIntent intent) {
+        Resources r = Resources.getSystem();
+        return (intent != null) ? intent.getTargetPackage()
+            : r.getString(R.string.sms_control_default_app_name);
+    }
+
+    /**
+     * Send the message along to the radio.
+     *
+     * @param tracker holds the SMS message to send
+     */
+    protected abstract void sendSms(SmsTracker tracker);
+
+    /**
+     * Send the multi-part SMS based on multipart Sms tracker
+     * 
+     * @param tracker holds the multipart Sms tracker ready to be sent
+     */
+    protected abstract void sendMultipartSms (SmsTracker tracker);
+
+    /**
+     * Activate or deactivate cell broadcast SMS.
+     *
+     * @param activate
+     *            0 = activate, 1 = deactivate
+     * @param response
+     *            Callback message is empty on completion
+     */
+    protected abstract void activateCellBroadcastSms(int activate, Message response);
+
+    /**
+     * Query the current configuration of cell broadcast SMS.
+     *
+     * @param response
+     *            Callback message contains the configuration from the modem on completion
+     *            @see #setCellBroadcastConfig
+     */
+    protected abstract void getCellBroadcastSmsConfig(Message response);
+
+    /**
+     * Configure cell broadcast SMS.
+     *
+     * @param configValuesArray
+     *          The first element defines the number of triples that follow.
+     *          A triple is made up of the service category, the language identifier
+     *          and a boolean that specifies whether the category is set active.
+     * @param response
+     *            Callback message is empty on completion
+     */
+    protected abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
+
+    /**
+     * Send an acknowledge message.
+     * @param success indicates that last message was successfully received.
+     * @param response callback message sent when operation completes.
+     */
+    protected abstract void acknowledgeLastIncomingSms(boolean success, Message response);
+
+    /**
+     * Check if a SmsTracker holds multi-part Sms
+     * 
+     * @param tracker a SmsTracker could hold a multi-part Sms
+     * @return true for tracker holds Multi-parts Sms
+     */
+    private boolean isMultipartTracker (SmsTracker tracker) {
+        HashMap map = tracker.mData;
+        return ( map.get("parts") != null);
+    }
+
+    /**
+     * Keeps track of an SMS that has been sent to the RIL, until it it has
+     * successfully been sent, or we're done trying.
+     *
+     */
+    static protected class SmsTracker {
+        // fields need to be public for derived SmsDispatchers
+        public HashMap mData;
+        public int mRetryCount;
+        public int mMessageRef;
+
+        public PendingIntent mSentIntent;
+        public PendingIntent mDeliveryIntent;
+
+        SmsTracker(HashMap data, PendingIntent sentIntent,
+                PendingIntent deliveryIntent) {
+            mData = data;
+            mSentIntent = sentIntent;
+            mDeliveryIntent = deliveryIntent;
+            mRetryCount = 0;
+        }
+    }
+    
+    protected SmsTracker SmsTrackerFactory(HashMap data, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        return new SmsTracker(data, sentIntent, deliveryIntent);
+    }
+
+    private DialogInterface.OnClickListener mListener =
+        new DialogInterface.OnClickListener() {
+
+            public void onClick(DialogInterface dialog, int which) {
+                if (which == DialogInterface.BUTTON_POSITIVE) {
+                    Log.d(TAG, "click YES to send out sms");
+                    sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS));
+                }
+            }
+        };
+}
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
new file mode 100644
index 0000000..7274e99
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.telephony.ServiceState;
+
+/**
+ * {@hide}
+ */
+public abstract class ServiceStateTracker extends Handler {
+    /**
+     *  The access technology currently in use:
+     *  0 = unknown
+     *  1 = GPRS only
+     *  2 = EDGE
+     *  3 = UMTS
+     */
+    protected static final int DATA_ACCESS_UNKNOWN = 0;
+    protected static final int DATA_ACCESS_GPRS = 1;
+    protected static final int DATA_ACCESS_EDGE = 2;
+    protected static final int DATA_ACCESS_UMTS = 3;
+    protected static final int DATA_ACCESS_CDMA_IS95A = 4;
+    protected static final int DATA_ACCESS_CDMA_IS95B = 5;
+    protected static final int DATA_ACCESS_CDMA_1xRTT = 6;
+    protected static final int DATA_ACCESS_CDMA_EvDo_0 = 7;
+    protected static final int DATA_ACCESS_CDMA_EvDo_A = 8;
+    //***** Instance Variables
+
+    protected CommandsInterface cm;
+
+    public ServiceState ss;
+    protected ServiceState newSS;
+
+    // Used as a unique identifier to track requests associated with a poll
+    // and ignore stale responses.The value is a count-down of expected responses
+    // in this pollingContext
+    protected int[] pollingContext;
+    protected boolean mDesiredPowerState;
+
+    protected boolean dontPollSignalStrength = false; // Default is to poll strength
+    // If we're getting unsolicited signal strength updates from the radio,
+    // set value to true and don't bother polling any more
+
+    protected RegistrantList networkAttachedRegistrants = new RegistrantList();
+    protected RegistrantList roamingOnRegistrants = new RegistrantList();
+    protected RegistrantList roamingOffRegistrants = new RegistrantList();
+
+    //***** Constants
+
+    protected  static final boolean DBG = true;
+
+    // signal strength poll rate
+    protected static final int POLL_PERIOD_MILLIS = 20 * 1000;
+
+    // waiting period before recheck gprs and voice registration
+    public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
+
+    public static final int MAX_NUM_DATA_STATE_READS = 15;
+    public static final int DATA_STATE_POLL_SLEEP_MS = 100;
+
+    //*****GSM events
+    protected static final int EVENT_RADIO_STATE_CHANGED               = 1;
+    protected static final int EVENT_NETWORK_STATE_CHANGED             = 2;
+    protected static final int EVENT_GET_SIGNAL_STRENGTH               = 3;
+    protected static final int EVENT_POLL_STATE_REGISTRATION           = 4;
+    protected static final int EVENT_POLL_STATE_GPRS                   = 5;
+    protected static final int EVENT_POLL_STATE_OPERATOR               = 6;
+    protected static final int EVENT_POLL_SIGNAL_STRENGTH              = 10;
+    protected static final int EVENT_NITZ_TIME                         = 11;
+    protected static final int EVENT_SIGNAL_STRENGTH_UPDATE            = 12;
+    protected static final int EVENT_RADIO_AVAILABLE                   = 13;
+    protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14;
+    protected static final int EVENT_GET_LOC_DONE                      = 15;
+    protected static final int EVENT_SIM_RECORDS_LOADED                = 16;
+    protected static final int EVENT_SIM_READY                         = 17;
+    protected static final int EVENT_LOCATION_UPDATES_ENABLED          = 18;
+    protected static final int EVENT_GET_PREFERRED_NETWORK_TYPE        = 19;
+    protected static final int EVENT_SET_PREFERRED_NETWORK_TYPE        = 20;
+    protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE      = 21;
+    protected static final int EVENT_CHECK_REPORT_GPRS                 = 22;
+    protected static final int EVENT_RESTRICTED_STATE_CHANGED          = 23;
+
+    //*****CDMA events:
+    protected static final int EVENT_POLL_STATE_REGISTRATION_CDMA      = 24;
+    protected static final int EVENT_POLL_STATE_OPERATOR_CDMA          = 25;
+    protected static final int EVENT_RUIM_READY                        = 26;
+    protected static final int EVENT_RUIM_RECORDS_LOADED               = 27;
+    protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA = 28;
+    protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA         = 29;
+    protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA          = 30;
+    protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA        = 31;
+    protected static final int EVENT_GET_LOC_DONE_CDMA                 = 32;
+    protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA       = 33;
+    protected static final int EVENT_NV_LOADED                         = 34;
+
+    //***** Time Zones
+    protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
+
+    // List of ISO codes for countries that can have an offset of GMT+0
+    // when not in daylight savings time.  This ignores some small places
+    // such as the Canary Islands (Spain) and Danmarkshavn (Denmark).
+    // The list must be sorted by code.
+    protected static final String[] GMT_COUNTRY_CODES = {
+        "bf", // Burkina Faso
+        "ci", // Cote d'Ivoire
+        "eh", // Western Sahara
+        "fo", // Faroe Islands, Denmark
+        "gh", // Ghana
+        "gm", // Gambia
+        "gn", // Guinea
+        "gw", // Guinea Bissau
+        "ie", // Ireland
+        "lr", // Liberia
+        "is", // Iceland
+        "ma", // Morocco
+        "ml", // Mali
+        "mr", // Mauritania
+        "pt", // Portugal
+        "sl", // Sierra Leone
+        "sn", // Senegal
+        "st", // Sao Tome and Principe
+        "tg", // Togo
+        "uk", // U.K
+    };
+
+
+    //***** Constructors
+    public ServiceStateTracker() {
+
+    }
+
+
+    /**
+     * Registration point for combined roaming on
+     * combined roaming is true when roaming is true and ONS differs SPN
+     *
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public  void registerForRoamingOn(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        roamingOnRegistrants.add(r);
+
+        if (ss.getRoaming()) {
+            r.notifyRegistrant();
+        }
+    }
+
+    public  void unregisterForRoamingOn(Handler h) {
+        roamingOnRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for combined roaming off
+     * combined roaming is true when roaming is true and ONS differs SPN
+     *
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public  void registerForRoamingOff(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        roamingOffRegistrants.add(r);
+
+        if (!ss.getRoaming()) {
+            r.notifyRegistrant();
+        }
+    }
+
+    public  void unregisterForRoamingOff(Handler h) {
+        roamingOffRegistrants.remove(h);
+    }
+
+    /**
+     * Reregister network through toggle perferred network type
+     * This is a work aorund to deregister and register network since there is
+     * no ril api to set COPS=2 (deregister) only.
+     *
+     * @param onComplete is dispatched when this is complete.  it will be
+     * an AsyncResult, and onComplete.obj.exception will be non-null
+     * on failure.
+     */
+    public void reRegisterNetwork(Message onComplete) {
+        cm.getPreferredNetworkType(
+                obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
+    }
+
+
+    //***** Called from Phone
+    public void
+    setRadioPower(boolean power) {
+        mDesiredPowerState = power;
+
+        setPowerStateToDesired();
+    }
+
+
+    public void enableLocationUpdates() {
+        cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
+    }
+
+    public void disableLocationUpdates() {
+        cm.setLocationUpdates(false, null);
+    }
+
+    //***** Overridden from Handler
+    public abstract void handleMessage(Message msg);
+
+    //***** Protected abstract Methods
+    protected abstract void handlePollStateResult(int what, AsyncResult ar);
+    protected abstract void updateSpnDisplay();
+    protected abstract void setPowerStateToDesired();
+
+    /** Cancel a pending (if any) pollState() operation */
+    protected void cancelPollState() {
+        // This will effectively cancel the rest of the poll requests
+        pollingContext = new int[1];
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/SmsAddress.java b/telephony/java/com/android/internal/telephony/SmsAddress.java
new file mode 100644
index 0000000..b3892cb
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsAddress.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+public abstract class SmsAddress {
+    // From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
+    // and C.S0005-D table 2.7.1.3.2.4-2
+    public static final int TON_UNKNOWN = 0;
+    public static final int TON_INTERNATIONAL = 1;
+    public static final int TON_NATIONAL = 2;
+    public static final int TON_NETWORK = 3;
+    public static final int TON_SUBSCRIBER = 4;
+    public static final int TON_ALPHANUMERIC = 5;
+    public static final int TON_ABBREVIATED = 6;
+
+    public int ton;
+    public String address;
+    public byte[] origBytes;
+
+    /**
+     * Returns the address of the SMS message in String form or null if unavailable
+     */
+    public String getAddressString() {
+        return address;
+    }
+
+    /**
+     * Returns true if this is an alphanumeric address
+     */
+    public boolean isAlphanumeric() {
+        return ton == TON_ALPHANUMERIC;
+    }
+
+    /**
+     * Returns true if this is a network address
+     */
+    public boolean isNetworkSpecific() {
+        return ton == TON_NETWORK;
+    }
+
+    public boolean couldBeEmailGateway() {
+        // Some carriers seems to send email gateway messages in this form:
+        // from: an UNKNOWN TON, 3 or 4 digits long, beginning with a 5
+        // PID: 0x00, Data coding scheme 0x03
+        // So we just attempt to treat any message from an address length <= 4
+        // as an email gateway
+
+        return address.length() <= 4;
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
similarity index 78%
rename from telephony/java/com/android/internal/telephony/gsm/SmsHeader.java
rename to telephony/java/com/android/internal/telephony/SmsHeader.java
index 22366ec..64b884e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsHeader.java
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import com.android.internal.util.HexDump;
 
@@ -24,8 +24,7 @@
  * This class represents a SMS user data header.
  *
  */
-public class SmsHeader
-{
+public class SmsHeader {
     /** See TS 23.040 9.2.3.24 for description of this element ID. */
     public static final int CONCATENATED_8_BIT_REFERENCE = 0x00;
     /** See TS 23.040 9.2.3.24 for description of this element ID. */
@@ -42,6 +41,7 @@
 
     private byte[] m_data;
     private ArrayList<Element> m_elements = new ArrayList<Element>();
+    public int nbrOfHeaders;
 
     /**
      * Creates an SmsHeader object from raw user data header bytes.
@@ -49,36 +49,33 @@
      * @param data is user data header bytes
      * @return an SmsHeader object
      */
-    public static SmsHeader parse(byte[] data)
-    {
+    public static SmsHeader parse(byte[] data) {
         SmsHeader header = new SmsHeader();
         header.m_data = data;
 
         int index = 0;
-        while (index < data.length)
-        {
+        header.nbrOfHeaders = 0;
+        while (index < data.length) {
             int id = data[index++] & 0xff;
             int length = data[index++] & 0xff;
             byte[] elementData = new byte[length];
             System.arraycopy(data, index, elementData, 0, length);
             header.add(new Element(id, elementData));
             index += length;
+            header.nbrOfHeaders++;
         }
 
         return header;
     }
 
-    public SmsHeader()
-    {
-    }
+    public SmsHeader() { }
 
     /**
      * Returns the list of SmsHeader Elements that make up the header.
      *
      * @return the list of SmsHeader Elements.
      */
-    public ArrayList<Element> getElements()
-    {
+    public ArrayList<Element> getElements() {
         return m_elements;
     }
 
@@ -87,14 +84,12 @@
      *
      * @param element to add.
      */
-    public void add(Element element)
-    {
+    public void add(Element element) {
         m_elements.add(element);
     }
 
     @Override
-    public String toString()
-    {
+    public String toString() {
         StringBuilder builder = new StringBuilder();
 
         builder.append("UDH LENGTH: " + m_data.length + " octets");
@@ -104,40 +99,56 @@
 
         for (Element e : getElements()) {
             builder.append("  0x" + HexDump.toHexString((byte)e.getID()) + " - ");
-            switch (e.getID())
-            {
-                case CONCATENATED_8_BIT_REFERENCE:
-                {
+            switch (e.getID()) {
+                case CONCATENATED_8_BIT_REFERENCE: {
                     builder.append("Concatenated Short Message 8bit ref\n");
                     byte[] data = e.getData();
                     builder.append("    " + data.length + " (0x");
-                    builder.append(HexDump.toHexString((byte)data.length)+") Bytes - Information Element\n");
+                    builder.append(HexDump.toHexString((byte)data.length)
+                            + ") Bytes - Information Element\n");
                     builder.append("      " + data[0] + " : SM reference number\n");
                     builder.append("      " + data[1] + " : number of messages\n");
                     builder.append("      " + data[2] + " : this SM sequence number\n");
                     break;
                 }
 
-                case CONCATENATED_16_BIT_REFERENCE:
-                {
+                case CONCATENATED_16_BIT_REFERENCE: {
                     builder.append("Concatenated Short Message 16bit ref\n");
                     byte[] data = e.getData();
                     builder.append("    " + data.length + " (0x");
-                    builder.append(HexDump.toHexString((byte)data.length)+") Bytes - Information Element\n");
-                    builder.append("      " + (data[0] & 0xff) * 256 + (data[1] & 0xff) +
-                                   " : SM reference number\n");
+                    builder.append(HexDump.toHexString((byte)data.length)
+                            + ") Bytes - Information Element\n");
+                    builder.append("      " + (data[0] & 0xff) * 256 + (data[1] & 0xff)
+                            + " : SM reference number\n");
                     builder.append("      " + data[2] + " : number of messages\n");
                     builder.append("      " + data[3] + " : this SM sequence number\n");
                     break;
                 }
 
-                case APPLICATION_PORT_ADDRESSING_16_BIT:
+                case APPLICATION_PORT_ADDRESSING_8_BIT:
                 {
+                    builder.append("Application port addressing 8bit\n");
+                    byte[] data = e.getData();
+
+                    builder.append("    " + data.length + " (0x");
+                    builder.append(HexDump.toHexString(
+                            (byte)data.length) + ") Bytes - Information Element\n");
+
+                    int source = (data[0] & 0xff);
+                    builder.append("      " + source + " : DESTINATION port\n");
+
+                    int dest = (data[1] & 0xff);
+                    builder.append("      " + dest + " : SOURCE port\n");
+                    break;
+                }
+
+                case APPLICATION_PORT_ADDRESSING_16_BIT: {
                     builder.append("Application port addressing 16bit\n");
                     byte[] data = e.getData();
 
                     builder.append("    " + data.length + " (0x");
-                    builder.append(HexDump.toHexString((byte)data.length)+") Bytes - Information Element\n");
+                    builder.append(HexDump.toHexString((byte)data.length)
+                            + ") Bytes - Information Element\n");
 
                     int source = (data[0] & 0xff) << 8;
                     source |= (data[1] & 0xff);
@@ -149,8 +160,7 @@
                     break;
                 }
 
-                default:
-                {
+                default: {
                     builder.append("Unknown element\n");
                     break;
                 }
@@ -202,13 +212,11 @@
      * See TS 23.040 9.2.3.24.
      *
      */
-    public static class Element
-    {
+    public static class Element {
         private byte[] m_data;
         private int m_id;
 
-        public Element(int id, byte[] data)
-        {
+        public Element(int id, byte[] data) {
             m_id = id;
             m_data = data;
         }
@@ -218,8 +226,7 @@
          *
          * @return the IE identifier.
          */
-        public int getID()
-        {
+        public int getID() {
             return m_id;
         }
 
@@ -228,8 +235,7 @@
          *
          * @return element data.
          */
-        public byte[] getData()
-        {
+        public byte[] getData() {
             return m_data;
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
new file mode 100644
index 0000000..1aad38d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.util.Log;
+import com.android.internal.telephony.SmsHeader;
+import java.util.Arrays;
+
+import static android.telephony.SmsMessage.MessageClass;
+
+/**
+ * Base class declaring the specific methods and members for SmsMessage.
+ * {@hide}
+ */
+public abstract class SmsMessageBase {
+    private static final String LOG_TAG = "SMS";
+
+    /** {@hide} The address of the SMSC. May be null */
+    protected String scAddress;
+
+    /** {@hide} The address of the sender */
+    protected SmsAddress originatingAddress;
+
+    /** {@hide} The message body as a string. May be null if the message isn't text */
+    protected String messageBody;
+
+    /** {@hide} */
+    protected String pseudoSubject;
+
+    /** {@hide} Non-null if this is an email gateway message */
+    protected String emailFrom;
+
+    /** {@hide} Non-null if this is an email gateway message */
+    protected String emailBody;
+
+    /** {@hide} */
+    protected boolean isEmail;
+
+    /** {@hide} */
+    protected long scTimeMillis;
+
+    /** {@hide} The raw PDU of the message */
+    protected byte[] mPdu;
+
+    /** {@hide} The raw bytes for the user data section of the message */
+    protected byte[] userData;
+
+    /** {@hide} */
+    protected SmsHeader userDataHeader;
+
+    // "Message Waiting Indication Group"
+    // 23.038 Section 4
+    /** {@hide} */
+    protected boolean isMwi;
+
+    /** {@hide} */
+    protected boolean mwiSense;
+
+    /** {@hide} */
+    protected boolean mwiDontStore;
+
+    /**
+     * Indicates status for messages stored on the ICC.
+     */
+    protected int statusOnIcc = -1;
+
+    /**
+     * Record index of message in the EF.
+     */
+    protected int indexOnIcc = -1;
+
+    /** TP-Message-Reference - Message Reference of sent message. @hide */
+    public int messageRef;
+
+    public static abstract class SubmitPduBase  {
+        public byte[] encodedScAddress; // Null if not applicable.
+        public byte[] encodedMessage;
+
+        public String toString() {
+            return "SubmitPdu: encodedScAddress = "
+                    + Arrays.toString(encodedScAddress)
+                    + ", encodedMessage = "
+                    + Arrays.toString(encodedMessage);
+        }
+    }
+
+    /**
+     * Returns the address of the SMS service center that relayed this message
+     * or null if there is none.
+     */
+    public String getServiceCenterAddress() {
+        return scAddress;
+    }
+
+    /**
+     * Returns the originating address (sender) of this SMS message in String
+     * form or null if unavailable
+     */
+    public String getOriginatingAddress() {
+        if (originatingAddress == null) {
+            return null;
+        }
+
+        return originatingAddress.getAddressString();
+    }
+
+    /**
+     * Returns the originating address, or email from address if this message
+     * was from an email gateway. Returns null if originating address
+     * unavailable.
+     */
+    public String getDisplayOriginatingAddress() {
+        if (isEmail) {
+            return emailFrom;
+        } else {
+            return getOriginatingAddress();
+        }
+    }
+
+    /**
+     * Returns the message body as a String, if it exists and is text based.
+     * @return message body is there is one, otherwise null
+     */
+    public String getMessageBody() {
+        return messageBody;
+    }
+
+    /**
+     * Returns the class of this message.
+     */
+    public abstract MessageClass getMessageClass();
+
+    /**
+     * Returns the message body, or email message body if this message was from
+     * an email gateway. Returns null if message body unavailable.
+     */
+    public String getDisplayMessageBody() {
+        if (isEmail) {
+            return emailBody;
+        } else {
+            return getMessageBody();
+        }
+    }
+
+    /**
+     * Unofficial convention of a subject line enclosed in parens empty string
+     * if not present
+     */
+    public String getPseudoSubject() {
+        return pseudoSubject == null ? "" : pseudoSubject;
+    }
+
+    /**
+     * Returns the service centre timestamp in currentTimeMillis() format
+     */
+    public long getTimestampMillis() {
+        return scTimeMillis;
+    }
+
+    /**
+     * Returns true if message is an email.
+     *
+     * @return true if this message came through an email gateway and email
+     *         sender / subject / parsed body are available
+     */
+    public boolean isEmail() {
+        return isEmail;
+    }
+
+    /**
+     * @return if isEmail() is true, body of the email sent through the gateway.
+     *         null otherwise
+     */
+    public String getEmailBody() {
+        return emailBody;
+    }
+
+    /**
+     * @return if isEmail() is true, email from address of email sent through
+     *         the gateway. null otherwise
+     */
+    public String getEmailFrom() {
+        return emailFrom;
+    }
+
+    /**
+     * Get protocol identifier.
+     */
+    public abstract int getProtocolIdentifier();
+
+    /**
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
+     * SMS
+     */
+    public abstract boolean isReplace();
+
+    /**
+     * Returns true for CPHS MWI toggle message.
+     *
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
+     *         B.4.2
+     */
+    public abstract boolean isCphsMwiMessage();
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) clear message
+     */
+    public abstract boolean isMWIClearMessage();
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) set message
+     */
+    public abstract boolean isMWISetMessage();
+
+    /**
+     * returns true if this message is a "Message Waiting Indication Group:
+     * Discard Message" notification and should not be stored.
+     */
+    public abstract boolean isMwiDontStore();
+
+    /**
+     * returns the user data section minus the user data header if one was
+     * present.
+     */
+    public byte[] getUserData() {
+        return userData;
+    }
+
+    /**
+     * Returns an object representing the user data header
+     *
+     * @return an object representing the user data header
+     *
+     * {@hide}
+     */
+    public SmsHeader getUserDataHeader() {
+        return userDataHeader;
+    }
+
+    /**
+     * Returns the raw PDU for the message.
+     *
+     * @return the raw PDU for the message.
+     */
+    public byte[] getPdu() {
+        return mPdu;
+    }
+
+    /**
+     * For an SMS-STATUS-REPORT message, this returns the status field from
+     * the status report.  This field indicates the status of a previously
+     * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
+     * description of values.
+     *
+     * @return 0 indicates the previously sent message was received.
+     *         See TS 23.040, 9.9.2.3.15 for a description of other possible
+     *         values.
+     */
+    public abstract int getStatus();
+
+    /**
+     * Return true iff the message is a SMS-STATUS-REPORT message.
+     */
+    public abstract boolean isStatusReportMessage();
+
+    /**
+     * Returns true iff the <code>TP-Reply-Path</code> bit is set in
+     * this message.
+     */
+    public abstract boolean isReplyPathPresent();
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     */
+    public int getStatusOnIcc() {
+        return statusOnIcc;
+    }
+
+    /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     */
+    public int getIndexOnIcc() {
+        return indexOnIcc;
+    }
+
+    protected void parseMessageBody() {
+        if (originatingAddress.couldBeEmailGateway()) {
+            extractEmailAddressFromMessageBody();
+        }
+    }
+
+    /**
+     * Try to parse this message as an email gateway message -> Neither
+     * of the standard ways are currently supported: There are two ways
+     * specified in TS 23.040 Section 3.8 (not supported via this mechanism) -
+     * SMS message "may have its TP-PID set for internet electronic mail - MT
+     * SMS format: [<from-address><space>]<message> - "Depending on the
+     * nature of the gateway, the destination/origination address is either
+     * derived from the content of the SMS TP-OA or TP-DA field, or the
+     * TP-OA/TP-DA field contains a generic gateway address and the to/from
+     * address is added at the beginning as shown above." - multiple addreses
+     * separated by commas, no spaces - subject field delimited by '()' or '##'
+     * and '#' Section 9.2.3.24.11
+     */
+    protected void extractEmailAddressFromMessageBody() {
+
+        /*
+         * a little guesswork here. I haven't found doc for this.
+         * the format could be either
+         *
+         * 1. [x@y][ ]/[subject][ ]/[body]
+         * -or-
+         * 2. [x@y][ ]/[body]
+         */
+        int slash = 0, slash2 = 0, atSymbol = 0;
+
+        try {
+            slash = messageBody.indexOf(" /");
+            if (slash == -1) {
+                return;
+            }
+
+            atSymbol = messageBody.indexOf('@');
+            if (atSymbol == -1 || atSymbol > slash) {
+                return;
+            }
+
+            emailFrom = messageBody.substring(0, slash);
+
+            slash2 = messageBody.indexOf(" /", slash + 2);
+
+            if (slash2 == -1) {
+                pseudoSubject = null;
+                emailBody = messageBody.substring(slash + 2);
+            } else {
+                pseudoSubject = messageBody.substring(slash + 2, slash2);
+                emailBody = messageBody.substring(slash2 + 2);
+            }
+
+            isEmail = true;
+        } catch (Exception ex) {
+            Log.w(LOG_TAG,
+                    "extractEmailAddressFromMessageBody: exception slash="
+                    + slash + ", atSymbol=" + atSymbol + ", slash2="
+                    + slash2, ex);
+        }
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.aidl b/telephony/java/com/android/internal/telephony/SmsRawData.aidl
similarity index 93%
rename from telephony/java/com/android/internal/telephony/gsm/SmsRawData.aidl
rename to telephony/java/com/android/internal/telephony/SmsRawData.aidl
index 6f1a46d..b0b3e4f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.aidl
+++ b/telephony/java/com/android/internal/telephony/SmsRawData.aidl
@@ -14,6 +14,6 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 parcelable SmsRawData;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.java b/telephony/java/com/android/internal/telephony/SmsRawData.java
similarity index 96%
rename from telephony/java/com/android/internal/telephony/gsm/SmsRawData.java
rename to telephony/java/com/android/internal/telephony/SmsRawData.java
index a029d5c..891d942 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.java
+++ b/telephony/java/com/android/internal/telephony/SmsRawData.java
@@ -15,10 +15,10 @@
 */
 
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  *  A parcelable holder class of byte[] for ISms aidl implementation
@@ -50,7 +50,7 @@
     public byte[] getBytes() {
         return data;
     }
-    
+
     public int describeContents() {
         return 0;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsResponse.java b/telephony/java/com/android/internal/telephony/SmsResponse.java
similarity index 88%
rename from telephony/java/com/android/internal/telephony/gsm/SmsResponse.java
rename to telephony/java/com/android/internal/telephony/SmsResponse.java
index c005b5f..3c4df56 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsResponse.java
+++ b/telephony/java/com/android/internal/telephony/SmsResponse.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * Object returned by the RIL upon successful completion of sendSMS.
  * Contains message reference and ackPdu.
  *
  */
-class SmsResponse {
+public class SmsResponse {
     /** Message reference of the just-sent SMS. */
     int messageRef;
     /** ackPdu for the just-sent SMS. */
     String ackPdu;
 
-    SmsResponse(int messageRef, String ackPdu) {
+    public SmsResponse(int messageRef, String ackPdu) {
         this.messageRef = messageRef;
         this.ackPdu = ackPdu;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/TelephonyEventLog.java b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
similarity index 92%
rename from telephony/java/com/android/internal/telephony/gsm/TelephonyEventLog.java
rename to telephony/java/com/android/internal/telephony/TelephonyEventLog.java
index 1e583f0..97f9d7d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/TelephonyEventLog.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /* This class contains the details related to Telephony Event Logging */
 public final class TelephonyEventLog {
@@ -28,6 +28,6 @@
     public static final int EVENT_LOG_RADIO_PDP_SETUP_FAIL = 50105;
     public static final int EVENT_LOG_CALL_DROP = 50106;
     public static final int EVENT_LOG_CGREG_FAIL = 50107;
-    public static final int EVENT_DATA_STATE_RADIO_OFF = 50108;
+    public static final int EVENT_LOG_DATA_STATE_RADIO_OFF = 50108;
     public static final int EVENT_LOG_PDP_NETWORK_DROP = 50109;
 }
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 9219e7a..c342233 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -35,6 +35,24 @@
      */
     public static final String ACTION_SERVICE_STATE_CHANGED = "android.intent.action.SERVICE_STATE";
 
+    /**
+     * <p>Broadcast Action: The radio technology has changed. The intent will have the following
+     * extra values:</p>
+     * <ul>
+     *   <li><em>phoneName</em> - A string version of the new phone name.</li>
+     * </ul>
+     *
+     * <p class="note">
+     * You can <em>not</em> receive this through components declared
+     * in manifests, only by explicitly registering for it with
+     * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,
+     * android.content.IntentFilter) Context.registerReceiver()}.
+     *
+     * <p class="note">
+     * Requires no permission.
+     */
+    public static final String ACTION_RADIO_TECHNOLOGY_CHANGED 
+            = "android.intent.action.RADIO_TECHNOLOGY";
 
     /**
      * Broadcast Action: The phone's signal strength has changed. The intent will have the
@@ -47,7 +65,7 @@
      *          <ul><li>0 means "-113 dBm or less".</li><li>31 means "-51 dBm or greater".</li></ul>
      *   </li>
      * </ul>
-     * 
+     *
      * <p class="note">
      * You can <em>not</em> receive this through components declared
      * in manifests, only by exlicitly registering for it with
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 6aa90f1..396b42d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -26,8 +26,11 @@
 {
     //****** Baseband and Radio Interface version
 
-    /** 
-     * Baseband version 
+    //TODO T: property strings do not have to be gsm specific
+    //        change gsm.*operator.*" properties to "operator.*" properties
+
+    /**
+     * Baseband version
      * Availability: property is available any time radio is on
      */
     static final String PROPERTY_BASEBAND_VERSION = "gsm.version.baseband";
@@ -47,6 +50,12 @@
      */
     static final String PROPERTY_OPERATOR_NUMERIC = "gsm.operator.numeric";
 
+    /** 'true' if the device is on a manually selected network
+     *
+     *  Availability: when registered to a network
+     */
+    static final String PROPERTY_OPERATOR_ISMANUAL = "operator.ismanual";
+
     /** 'true' if the device is considered roaming on this network for GSM
      *  purposes.
      *  Availability: when registered to a network
@@ -60,7 +69,7 @@
     static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country";
 
     //****** SIM Card
-    /** 
+    /**
      * One of <code>"UNKNOWN"</code> <code>"ABSENT"</code> <code>"PIN_REQUIRED"</code>
      * <code>"PUK_REQUIRED"</code> <code>"NETWORK_LOCKED"</code> or <code>"READY"</code>
      */
@@ -70,15 +79,15 @@
      *  provider of the SIM. 5 or 6 decimal digits.
      *  Availablity: SIM state must be "READY"
      */
-    static String PROPERTY_SIM_OPERATOR_NUMERIC = "gsm.sim.operator.numeric";
+    static String PROPERTY_ICC_OPERATOR_NUMERIC = "gsm.sim.operator.numeric";
 
-    /** PROPERTY_SIM_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name. 
+    /** PROPERTY_ICC_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name.
      *  Availablity: SIM state must be "READY"
      */
-    static String PROPERTY_SIM_OPERATOR_ALPHA = "gsm.sim.operator.alpha";
+    static String PROPERTY_ICC_OPERATOR_ALPHA = "gsm.sim.operator.alpha";
 
     /** ISO country code equivalent for the SIM provider's country code*/
-    static String PROPERTY_SIM_OPERATOR_ISO_COUNTRY = "gsm.sim.operator.iso-country";
+    static String PROPERTY_ICC_OPERATOR_ISO_COUNTRY = "gsm.sim.operator.iso-country";
 
     /**
      * Indicates the available radio technology.  Values include: <code>"unknown"</code>,
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
index 2b70162..98899c9 100644
--- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -22,7 +22,6 @@
 import android.provider.Telephony.Sms.Intents;
 import android.util.Config;
 import android.util.Log;
-import com.android.internal.telephony.gsm.SimUtils;
 
 
 /**
@@ -44,6 +43,7 @@
     private final int WAKE_LOCK_TIMEOUT = 5000;
 
     public WapPushOverSms(Phone phone) {
+
         mContext = phone.getContext();
         createWakelock();
     }
@@ -56,7 +56,7 @@
      */
     public void dispatchWapPdu(byte[] pdu) {
 
-        if (Config.LOGD) Log.d(LOG_TAG, "Rx: " + SimUtils.bytesToHexString(pdu));
+        if (Config.LOGD) Log.d(LOG_TAG, "Rx: " + IccUtils.bytesToHexString(pdu));
 
         int index = 0;
         int transactionId = pdu[index++] & 0xFF;
@@ -225,3 +225,4 @@
         mContext.sendBroadcast(intent, permission);
     }
 }
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
new file mode 100755
index 0000000..8ffb7ec
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -0,0 +1,911 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telephony.CellLocation;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
+import android.text.TextUtils;
+import android.util.Log;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
+
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.PhoneSubInfo;
+import com.android.internal.telephony.RILConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@hide}
+ */
+public class CDMAPhone extends PhoneBase {
+    static final String LOG_TAG = "CDMA";
+    private static final boolean LOCAL_DEBUG = true;
+
+    //***** Instance Variables
+    CdmaCallTracker mCT;
+    CdmaSMSDispatcher mSMS;
+    CdmaServiceStateTracker mSST;
+    CdmaDataConnectionTracker mDataConnection;
+    RuimFileHandler mRuimFileHandler;
+    RuimRecords mRuimRecords;
+    RuimCard mRuimCard;
+    MyHandler h;
+    RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
+    RuimSmsInterfaceManager mRuimSmsInterfaceManager;
+    PhoneSubInfo mSubInfo;
+
+    protected RegistrantList mNvLoadedRegistrants = new RegistrantList();
+    private String mEsn;
+    private String mMeid;
+
+    Registrant mPostDialHandler;
+
+
+    //***** Constructors
+    public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
+        this(context,ci,notifier, false);
+    }
+
+    public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
+            boolean unitTestMode) {
+        super(notifier, context, unitTestMode);
+
+        h = new MyHandler();
+        mCM = ci;
+
+        mCM.setPhoneType(RILConstants.CDMA_PHONE);
+        mCT = new CdmaCallTracker(this);
+        mSST = new CdmaServiceStateTracker (this);
+        mSMS = new CdmaSMSDispatcher(this);
+        mIccFileHandler = new RuimFileHandler(this);
+        mRuimRecords = new RuimRecords(this);
+        mDataConnection = new CdmaDataConnectionTracker (this);
+        mRuimCard = new RuimCard(this);
+        mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
+        mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this);
+        mSubInfo = new PhoneSubInfo(this);
+
+        mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
+        mRuimRecords.registerForRecordsLoaded(h, EVENT_RUIM_RECORDS_LOADED, null);
+        mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        mCM.registerForOn(h, EVENT_RADIO_ON, null);
+        mCM.setOnSuppServiceNotification(h, EVENT_SSN, null);
+        mCM.setOnCallRing(h, EVENT_CALL_RING, null);
+        mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
+        mCM.registerForNVReady(h, EVENT_NV_READY, null);
+
+        //Change the system setting
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.CDMA_PHONE);
+    }
+
+    public void dispose() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+
+            //Unregister from all former registered events
+            mRuimRecords.unregisterForRecordsLoaded(h); //EVENT_RUIM_RECORDS_LOADED
+            mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE
+            mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
+            mCM.unregisterForOn(h); //EVENT_RADIO_ON
+            mCM.unregisterForNVReady(h); //EVENT_NV_READY
+            mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
+            mCM.unSetOnSuppServiceNotification(h);
+            mCM.unSetOnCallRing(h);
+
+            //Force all referenced classes to unregister their former registered events
+            mCT.dispose();
+            mDataConnection.dispose();
+            mSST.dispose();
+            mSMS.dispose();
+            mIccFileHandler.dispose(); // instance of RuimFileHandler
+            mRuimRecords.dispose();
+            mRuimCard.dispose();
+            mRuimPhoneBookInterfaceManager.dispose();
+            mRuimSmsInterfaceManager.dispose();
+            mSubInfo.dispose();
+        }
+    }
+
+    public void removeReferences() {
+            this.mRuimPhoneBookInterfaceManager = null;
+            this.mRuimSmsInterfaceManager = null;
+            this.mSMS = null;
+            this.mSubInfo = null;
+            this.mRuimRecords = null;
+            this.mIccFileHandler = null;
+            this.mRuimCard = null;
+            this.mDataConnection = null;
+            this.mCT = null;
+            this.mSST = null;
+    }
+
+    protected void finalize() {
+        if(LOCAL_DEBUG) Log.d(LOG_TAG, "CDMAPhone finalized");
+    }
+
+
+    //***** Overridden from Phone
+    public ServiceState getServiceState() {
+        return mSST.ss;
+    }
+
+    public Phone.State
+    getState() {
+        return mCT.state;
+    }
+
+    public String
+    getPhoneName() {
+        return "CDMA";
+    }
+
+    public boolean canTransfer() {
+        Log.e(LOG_TAG, "canTransfer: not possible in CDMA");
+        return false;
+    }
+
+    public CdmaCall
+    getRingingCall() {
+        return mCT.ringingCall;
+    }
+
+    public void setMute(boolean muted) {
+        mCT.setMute(muted);
+    }
+
+    public boolean getMute() {
+        return mCT.getMute();
+    }
+
+    public void conference() throws CallStateException {
+        // three way calls in CDMA will be handled by feature codes
+        Log.e(LOG_TAG, "conference: not possible in CDMA");
+    }
+
+    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
+        this.mCM.setPreferredVoicePrivacy(enable, onComplete);
+    }
+
+    public void getEnhancedVoicePrivacy(Message onComplete) {
+        this.mCM.getPreferredVoicePrivacy(onComplete);
+    }
+
+    public void clearDisconnected() {
+        mCT.clearDisconnected();
+    }
+
+    public DataActivityState getDataActivityState() {
+        DataActivityState ret = DataActivityState.NONE;
+
+        if (mSST.getCurrentCdmaDataConnectionState() != ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
+
+            switch (mDataConnection.getActivity()) {
+                case DATAIN:
+                    ret = DataActivityState.DATAIN;
+                break;
+
+                case DATAOUT:
+                    ret = DataActivityState.DATAOUT;
+                break;
+
+                case DATAINANDOUT:
+                    ret = DataActivityState.DATAINANDOUT;
+                break;
+            }
+        }
+        return ret;
+    }
+
+    /*package*/ void
+    notifySignalStrength() {
+        mNotifier.notifySignalStrength(this);
+    }
+
+    public Connection
+    dial (String dialString) throws CallStateException {
+        // Need to make sure dialString gets parsed properly
+        String newDialString = PhoneNumberUtils.stripSeparators(dialString);
+
+        if (!mCT.foregroundCall.isIdle()) {
+            FeatureCode fc = FeatureCode.newFromDialString(newDialString, this);
+            if (fc != null) {
+                //mMmiRegistrants.notifyRegistrants(new AsyncResult(null, fc, null));
+                fc.processCode();
+            } else {
+                FeatureCode digits = new FeatureCode(this);
+                // use dial number as poundString
+                digits.poundString = newDialString;
+                digits.processCode();
+            }
+            return null;
+        } else {
+            return mCT.dial(newDialString);
+        }
+    }
+
+
+    public int getSignalStrengthASU() {
+        return mSST.rssi == 99 ? -1 : mSST.rssi;
+    }
+
+    public boolean
+    getMessageWaitingIndicator() {
+        return mRuimRecords.getVoiceMessageWaiting();
+    }
+
+    public List<? extends MmiCode>
+    getPendingMmiCodes() {
+        Log.e(LOG_TAG, "method getPendingMmiCodes is NOT supported in CDMA!");
+        return null;
+    }
+
+    public void registerForSuppServiceNotification(
+            Handler h, int what, Object obj) {
+        Log.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!");
+    }
+
+    public CdmaCall getBackgroundCall() {
+        return mCT.backgroundCall;
+    }
+
+    public String getGateway(String apnType) {
+        return mDataConnection.getGateway();
+    }
+
+    public boolean handleInCallMmiCommands(String dialString) {
+        Log.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
+        return false;
+    }
+
+    public int enableApnType(String type) {
+        // This request is mainly used to enable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to enableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_ALREADY_ACTIVE;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    public int disableApnType(String type) {
+        // This request is mainly used to disable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to disableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_REQUEST_STARTED;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    public String getActiveApn() {
+        Log.d(LOG_TAG, "Request to getActiveApn()");
+        return null;
+    }
+
+    public void
+    setNetworkSelectionModeAutomatic(Message response) {
+        Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!");
+    }
+
+    public void unregisterForSuppServiceNotification(Handler h) {
+        Log.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!");
+    }
+
+    public void
+    acceptCall() throws CallStateException {
+        mCT.acceptCall();
+    }
+
+    public void
+    rejectCall() throws CallStateException {
+        mCT.rejectCall();
+    }
+
+    public void
+    switchHoldingAndActive() throws CallStateException {
+        mCT.switchWaitingOrHoldingAndActive();
+    }
+
+    public String getLine1Number() {
+        return mRuimRecords.getMdnNumber();
+    }
+
+    public void getCallWaiting(Message onComplete) {
+        mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
+    }
+
+    public void
+    setRadioPower(boolean power) {
+        mSST.setRadioPower(power);
+    }
+
+    public String getEsn() {
+        return mEsn;
+    }
+
+    public String getMeid() {
+        return mMeid;
+    }
+
+    //returns MEID in CDMA
+    public String getDeviceId() {
+        return getMeid();
+    }
+
+    public String getDeviceSvn() {
+        Log.d(LOG_TAG, "getDeviceSvn(): return 0");
+        return "0";
+    }
+
+    public String getSubscriberId() {
+        Log.e(LOG_TAG, "method getSubscriberId for IMSI is NOT supported in CDMA!");
+        return null;
+    }
+
+    public boolean canConference() {
+        Log.e(LOG_TAG, "canConference: not possible in CDMA");
+        return false;
+    }
+
+    public String getInterfaceName(String apnType) {
+        return mDataConnection.getInterfaceName();
+    }
+
+    public CellLocation getCellLocation() {
+        return mSST.cellLoc;
+    }
+
+    public boolean disableDataConnectivity() {
+        return mDataConnection.setDataEnabled(false);
+    }
+
+    public CdmaCall getForegroundCall() {
+        return mCT.foregroundCall;
+    }
+
+    public void
+    selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network,
+            Message response) {
+        Log.e(LOG_TAG, "selectNetworkManually: not possible in CDMA");
+    }
+
+    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
+        Log.e(LOG_TAG, "setOnPostDialCharacter: not possible in CDMA");
+    }
+
+    public boolean handlePinMmi(String dialString) {
+        Log.e(LOG_TAG, "method handlePinMmi is NOT supported in CDMA!");
+        return false;
+    }
+
+    public boolean isDataConnectivityPossible() {
+        boolean noData = mDataConnection.getDataEnabled() &&
+                getDataConnectionState() == DataState.DISCONNECTED;
+        return !noData && getIccCard().getState() == IccCard.State.READY &&
+                getServiceState().getState() == ServiceState.STATE_IN_SERVICE &&
+                (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming());
+    }
+
+    public void setLine1Number(String alphaTag, String number, Message onComplete) {
+        Log.e(LOG_TAG, "setLine1Number: not possible in CDMA");
+    }
+
+    public String[] getDnsServers(String apnType) {
+        return mDataConnection.getDnsServers();
+    }
+
+    public IccCard getIccCard() {
+        return mRuimCard;
+    }
+
+    public String getIccSerialNumber() {
+        return mRuimRecords.iccid;
+    }
+
+    public void setCallWaiting(boolean enable, Message onComplete) {
+        Log.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
+    }
+
+    public void updateServiceLocation(Message response) {
+        mSST.getLacAndCid(response);
+    }
+
+    public void setDataRoamingEnabled(boolean enable) {
+        mDataConnection.setDataOnRoamingEnabled(enable);
+    }
+
+    public String getIpAddress(String apnType) {
+        return mDataConnection.getIpAddress();
+    }
+
+    public void
+    getNeighboringCids(Message response) {
+        // WINK:TODO: implement after Cupcake merge
+        mCM.getNeighboringCids(response); // workaround.
+    }
+
+    public DataState getDataConnectionState() {
+        DataState ret = DataState.DISCONNECTED;
+
+        if ((SystemProperties.get("adb.connected", "").length() > 0)
+                && (SystemProperties.get("android.net.use-adb-networking", "")
+                        .length() > 0)) {
+            // We're connected to an ADB host and we have USB networking
+            // turned on. No matter what the radio state is,
+            // we report data connected
+
+            ret = DataState.CONNECTED;
+        } else if (mSST == null) {
+            // Radio Technology Change is ongoning, dispose() and removeReferences() have
+            // already been called
+
+            ret = DataState.DISCONNECTED;
+        } else if (mSST.getCurrentCdmaDataConnectionState()
+                == ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
+            // If we're out of service, open TCP sockets may still work
+            // but no data will flow
+            ret = DataState.DISCONNECTED;
+        } else {
+            switch (mDataConnection.getState()) {
+                case FAILED:
+                case IDLE:
+                    ret = DataState.DISCONNECTED;
+                break;
+
+                case CONNECTED:
+                case DISCONNECTING:
+                    if ( mCT.state != Phone.State.IDLE
+                            && !mSST.isConcurrentVoiceAndData()) {
+                        ret = DataState.SUSPENDED;
+                    } else {
+                        ret = DataState.CONNECTED;
+                    }
+                break;
+
+                case INITING:
+                case CONNECTING:
+                case SCANNING:
+                    ret = DataState.CONNECTING;
+                break;
+            }
+        }
+
+        return ret;
+    }
+
+    public void sendUssdResponse(String ussdMessge) {
+        Log.e(LOG_TAG, "sendUssdResponse: not possible in CDMA");
+    }
+
+    public void sendDtmf(char c) {
+        if (!PhoneNumberUtils.is12Key(c)) {
+            Log.e(LOG_TAG,
+                    "sendDtmf called with invalid character '" + c + "'");
+        } else {
+            if (mCT.state ==  Phone.State.OFFHOOK) {
+                mCM.sendDtmf(c, null);
+            }
+        }
+    }
+
+    public void startDtmf(char c) {
+        if (!PhoneNumberUtils.is12Key(c)) {
+            Log.e(LOG_TAG,
+                    "startDtmf called with invalid character '" + c + "'");
+        } else {
+            mCM.startDtmf(c, null);
+        }
+    }
+
+    public void stopDtmf() {
+        mCM.stopDtmf(null);
+    }
+
+    public void getAvailableNetworks(Message response) {
+        Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
+    }
+
+    public String[] getActiveApnTypes() {
+        String[] result;
+        Log.d(LOG_TAG, "Request to getActiveApn()");
+        result = new String[1];
+        result[0] = Phone.APN_TYPE_DEFAULT;
+        return result;
+    }
+
+    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
+        Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
+    }
+
+    public void enableLocationUpdates() {
+        mSST.enableLocationUpdates();
+    }
+
+    /**
+     * @deprecated
+     */
+    public void getPdpContextList(Message response) {
+        getDataCallList(response);
+    }
+
+    public void getDataCallList(Message response) {
+        mCM.getDataCallList(response);
+    }
+
+    public boolean getDataRoamingEnabled() {
+        return mDataConnection.getDataOnRoamingEnabled();
+    }
+
+    public List<DataConnection> getCurrentDataConnectionList () {
+        return mDataConnection.getAllDataConnections();
+    }
+
+    public void setVoiceMailNumber(String alphaTag,
+                                   String voiceMailNumber,
+                                   Message onComplete) {
+        //mSIMRecords.setVoiceMailNumber(alphaTag, voiceMailNumber, onComplete);
+        //TODO: Where do we have to store this value has to be clarified with QC
+    }
+
+    public String getVoiceMailNumber() {
+        //TODO: Where can we get this value has to be clarified with QC
+        //return mSIMRecords.getVoiceMailNumber();
+//      throw new RuntimeException();
+        return "12345";
+    }
+
+    public String getVoiceMailAlphaTag() {
+        // TODO: Where can we get this value has to be clarified with QC.
+        String ret = "";//TODO: Remove = "", if we know where to get this value.
+
+        //ret = mSIMRecords.getVoiceMailAlphaTag();
+
+        if (ret == null || ret.length() == 0) {
+            return mContext.getText(
+                com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
+        }
+
+        return ret;
+    }
+
+    public boolean enableDataConnectivity() {
+        return mDataConnection.setDataEnabled(true);
+    }
+
+    public void disableLocationUpdates() {
+        mSST.disableLocationUpdates();
+    }
+
+    public boolean getIccRecordsLoaded() {
+        return mRuimRecords.getRecordsLoaded();
+    }
+
+    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
+        Log.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
+    }
+
+    public void setCallForwardingOption(int commandInterfaceCFAction,
+            int commandInterfaceCFReason,
+            String dialingNumber,
+            int timerSeconds,
+            Message onComplete) {
+        Log.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA");
+    }
+
+    public void
+    getOutgoingCallerIdDisplay(Message onComplete) {
+        Log.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA");
+    }
+
+    public boolean
+    getCallForwardingIndicator() {
+        Log.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
+        return false;
+    }
+
+    public void explicitCallTransfer() {
+        Log.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA");
+    }
+
+    public String getLine1AlphaTag() {
+        Log.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA");
+        return null;
+    }
+
+    /**
+     * Notify any interested party of a Phone state change.
+     */
+    /*package*/ void notifyPhoneStateChanged() {
+        mNotifier.notifyPhoneState(this);
+    }
+
+    /**
+     * Notifies registrants (ie, activities in the Phone app) about
+     * changes to call state (including Phone and Connection changes).
+     */
+    /*package*/ void notifyCallStateChanged() {
+        /* we'd love it if this was package-scoped*/
+        super.notifyCallStateChangedP();
+    }
+
+     void notifyServiceStateChanged(ServiceState ss) {
+         super.notifyServiceStateChangedP(ss);
+     }
+
+     void notifyLocationChanged() {
+         mNotifier.notifyCellLocation(this);
+     }
+
+    /*package*/ void notifyNewRingingConnection(Connection c) {
+        /* we'd love it if this was package-scoped*/
+        super.notifyNewRingingConnectionP(c);
+    }
+
+    /**
+     * Notifiy registrants of a RING event.
+     */
+    void notifyIncomingRing() {
+        AsyncResult ar = new AsyncResult(null, this, null);
+        mIncomingRingRegistrants.notifyRegistrants(ar);
+    }
+
+    /*package*/ void notifyDisconnect(Connection cn) {
+        mDisconnectRegistrants.notifyResult(cn);
+    }
+
+    void notifyUnknownConnection() {
+        mUnknownConnectionRegistrants.notifyResult(this);
+    }
+
+    /*package*/ void
+    updateMessageWaitingIndicator(boolean mwi) {
+        // this also calls notifyMessageWaitingIndicator()
+        mRuimRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
+    }
+
+    public void
+    notifyMessageWaitingIndicator() {
+        mNotifier.notifyMessageWaitingChanged(this);
+    }
+
+    /**
+     * Removes the given FC from the pending list and notifies
+     * registrants that it is complete.
+     * @param fc FC that is done
+     */
+    /*package*/ void onFeatureCodeDone(FeatureCode fc) {
+        /* Only notify complete if it's on the pending list.
+         * Otherwise, it's already been handled (eg, previously canceled).
+         * The exception is cancellation of an incoming USSD-REQUEST, which is
+         * not on the list.
+         */
+         mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, fc, null));
+    }
+
+    //***** Inner Classes
+    class MyHandler extends Handler {
+        MyHandler() {
+        }
+
+        MyHandler(Looper l) {
+            super(l);
+        }
+
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+            Message     onComplete;
+
+            switch(msg.what) {
+                case EVENT_RADIO_AVAILABLE: {
+                    mCM.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
+
+                    mCM.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
+                }
+                break;
+
+                case EVENT_GET_BASEBAND_VERSION_DONE:{
+                    ar = (AsyncResult)msg.obj;
+
+                    if (ar.exception != null) {
+                        break;
+                    }
+
+                    if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
+                    setSystemProperty(PROPERTY_BASEBAND_VERSION, (String)ar.result);
+                }
+                break;
+
+                case EVENT_GET_DEVICE_IDENTITY_DONE:{
+                    ar = (AsyncResult)msg.obj;
+
+                    if (ar.exception != null) {
+                        break;
+                    }
+                    String[] respId = (String[])ar.result;
+                    mEsn  =  respId[2];
+                    mMeid =  respId[3];
+                }
+                break;
+
+                case EVENT_RUIM_RECORDS_LOADED:{
+                    Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
+                }
+                break;
+
+                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{
+                    Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
+                }
+                break;
+
+                case EVENT_RADIO_ON:{
+                    Log.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
+                }
+                break;
+
+                case EVENT_SSN:{
+                    Log.d(LOG_TAG, "Event EVENT_SSN Received");
+                }
+                break;
+
+                case EVENT_CALL_RING:{
+                    Log.d(LOG_TAG, "Event EVENT_CALL_RING Received");
+                }
+                break;
+
+                case EVENT_REGISTERED_TO_NETWORK:{
+                    Log.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received");
+                }
+                break;
+
+                case EVENT_NV_READY:{
+                    Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
+                    //Inform the Service State Tracker
+                    mNvLoadedRegistrants.notifyRegistrants();
+                }
+                break;
+
+                default:{
+                    throw new RuntimeException("unexpected event not handled");
+                }
+            }
+        }
+    }
+
+     /**
+      * Retrieves the PhoneSubInfo of the CDMAPhone
+      */
+     public PhoneSubInfo getPhoneSubInfo(){
+        return mSubInfo;
+     }
+
+     /**
+      * Retrieves the IccSmsInterfaceManager of the CDMAPhone
+      */
+     public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+         return mRuimSmsInterfaceManager;
+     }
+
+     /**
+      * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone
+      */
+     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+         return mRuimPhoneBookInterfaceManager;
+     }
+
+    public void registerForNvLoaded(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mNvLoadedRegistrants.add(r);
+    }
+
+    public void unregisterForNvLoaded(Handler h) {
+        mNvLoadedRegistrants.remove(h);
+    }
+
+     // override for allowing access from other classes of this package
+     /**
+      * {@inheritDoc}
+      */
+     public final void setSystemProperty(String property, String value) {
+         super.setSystemProperty(property, value);
+     }
+
+     /**
+      * {@inheritDoc}
+      */
+     public Handler getHandler(){
+         return h;
+     }
+
+     /**
+      * {@inheritDoc}
+      */
+     public IccFileHandler getIccFileHandler(){
+         return this.mIccFileHandler;
+     }
+
+     /**
+      * Set the TTY mode of the CDMAPhone
+      */
+     public void setTTYModeEnabled(boolean enable, Message onComplete) {
+         this.mCM.setTTYModeEnabled(enable, onComplete);
+}
+
+     /**
+      * Queries the TTY mode of the CDMAPhone
+      */
+     public void queryTTYModeEnabled(Message onComplete) {
+         this.mCM.queryTTYModeEnabled(onComplete);
+     }
+
+     /**
+      * Activate or deactivate cell broadcast SMS.
+      *
+      * @param activate
+      *            0 = activate, 1 = deactivate
+      * @param response
+      *            Callback message is empty on completion
+      */
+     public void activateCellBroadcastSms(int activate, Message response) {
+         mSMS.activateCellBroadcastSms(activate, response);
+     }
+
+     /**
+      * Query the current configuration of cdma cell broadcast SMS.
+      *
+      * @param response
+      *            Callback message is empty on completion
+      */
+     public void getCellBroadcastSmsConfig(Message response){
+         mSMS.getCellBroadcastSmsConfig(response);
+     }
+
+     /**
+      * Configure cdma cell broadcast SMS.
+      *
+      * @param response
+      *            Callback message is empty on completion
+      */
+     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
+         mSMS.setCellBroadcastConfig(configValuesArray, response);
+     }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
new file mode 100644
index 0000000..ea557b2
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+/**
+ * Call fail causes from TS 24.008 .
+ * These are mostly the cause codes we need to distinguish for the UI.
+ * See 22.001 Annex F.4 for mapping of cause codes to local tones.
+ *
+ * {@hide}
+ *
+ */
+public interface CallFailCause {
+    static final int NORMAL_CLEARING     = 16;
+    // Busy Tone
+    static final int USER_BUSY           = 17;
+
+//    // No Tone
+//    static final int NUMBER_CHANGED      = 22;
+//    static final int STATUS_ENQUIRY      = 30;
+    static final int NORMAL_UNSPECIFIED  = 31;
+//
+//    // Congestion Tone
+//    static final int NO_CIRCUIT_AVAIL    = 34;
+//    static final int TEMPORARY_FAILURE   = 41;
+//    static final int SWITCHING_CONGESTION    = 42;
+//    static final int CHANNEL_NOT_AVAIL   = 44;
+//    static final int QOS_NOT_AVAIL       = 49;
+//    static final int BEARER_NOT_AVAIL    = 58;
+//
+//    // others
+//    static final int ACM_LIMIT_EXCEEDED = 68;
+//    static final int CALL_BARRED        = 240;
+//    static final int FDN_BLOCKED        = 241;
+    static final int ERROR_UNSPECIFIED = 0xffff;
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCall.java
similarity index 73%
copy from telephony/java/com/android/internal/telephony/gsm/GSMCall.java
copy to telephony/java/com/android/internal/telephony/cdma/CdmaCall.java
index 4feaf21..34514d9 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCall.java
@@ -14,27 +14,31 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+package com.android.internal.telephony.cdma;
+
 import java.util.ArrayList;
 import java.util.List;
 
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.Phone;
+
 /**
  * {@hide}
  */
-class GSMCall extends Call
-{
+public final class CdmaCall extends Call {
     /*************************** Instance Variables **************************/
 
     /*package*/ ArrayList<Connection> connections = new ArrayList<Connection>();
     /*package*/ State state = State.IDLE;
-    /*package*/ CallTracker owner;
+    /*package*/ CdmaCallTracker owner;
 
     /***************************** Class Methods *****************************/
 
     static State
-    stateFromDCState (DriverCall.State dcState)
-    {
+    stateFromDCState (DriverCall.State dcState) {
         switch (dcState) {
             case ACTIVE:        return State.ACTIVE;
             case HOLDING:       return State.HOLDING;
@@ -45,40 +49,36 @@
             default:            throw new RuntimeException ("illegal call state:" + dcState);
         }
     }
-    
+
 
     /****************************** Constructors *****************************/
     /*package*/
-    GSMCall (CallTracker owner)
-    {
+    CdmaCall (CdmaCallTracker owner) {
         this.owner = owner;
     }
 
-    /************************** Overridden from Call *************************/
+    public void dispose() {
+    }
 
+    /************************** Overridden from Call *************************/
     public List<Connection>
-    getConnections()
-    {
+    getConnections() {
         // FIXME should return Collections.unmodifiableList();
         return connections;
     }
 
-    public State 
-    getState()
-    {
+    public State
+    getState() {
         return state;
     }
 
-    public Phone 
-    getPhone()
-    {
-        //TODO
+    public Phone
+    getPhone() {
+        //TODO, see GsmCall
         return null;
     }
 
-    public boolean
-    isMultiparty()
-    {
+    public boolean isMultiparty() {
         return connections.size() > 1;
     }
 
@@ -86,66 +86,60 @@
      *  background call exists, the background call will be resumed
      *  because an AT+CHLD=1 will be sent
      */
-    public void 
-    hangup() throws CallStateException
-    {
+    public void
+    hangup() throws CallStateException {
         owner.hangup(this);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return state.toString();
     }
 
-    //***** Called from GSMConnection
+    //***** Called from CdmaConnection
 
     /*package*/ void
-    attach(GSMConnection conn, DriverCall dc)
-    {
+    attach(Connection conn, DriverCall dc) {
         connections.add(conn);
 
         state = stateFromDCState (dc.state);
     }
 
     /*package*/ void
-    attachFake(GSMConnection conn, State state)
-    {
+    attachFake(Connection conn, State state) {
         connections.add(conn);
 
         this.state = state;
     }
 
     /**
-     * Called by GSMConnection when it has disconnected
+     * Called by CdmaConnection when it has disconnected
      */
     void
-    connectionDisconnected(GSMConnection conn)
-    {
+    connectionDisconnected(CdmaConnection conn) {
         if (state != State.DISCONNECTED) {
             /* If only disconnected connections remain, we are disconnected*/
 
             boolean hasOnlyDisconnectedConnections = true;
-            
+
             for (int i = 0, s = connections.size()  ; i < s; i ++) {
-                if (connections.get(i).getState() 
+                if (connections.get(i).getState()
                     != State.DISCONNECTED
                 ) {
                     hasOnlyDisconnectedConnections = false;
                     break;
-                }            
+                }
             }
 
             if (hasOnlyDisconnectedConnections) {
-                state = State.DISCONNECTED;            
+                state = State.DISCONNECTED;
             }
-        }    
+        }
     }
 
 
     /*package*/ void
-    detach(GSMConnection conn)
-    {
+    detach(CdmaConnection conn) {
         connections.remove(conn);
 
         if (connections.size() == 0) {
@@ -154,13 +148,12 @@
     }
 
     /*package*/ boolean
-    update (GSMConnection conn, DriverCall dc)
-    {
+    update (CdmaConnection conn, DriverCall dc) {
         State newState;
         boolean changed = false;
-        
+
         newState = stateFromDCState(dc.state);
-        
+
         if (newState != state) {
             state = newState;
             changed = true;
@@ -174,48 +167,43 @@
      * connections to be added via "conference"
      */
     /*package*/ boolean
-    isFull()
-    {
-        return connections.size() == CallTracker.MAX_CONNECTIONS_PER_CALL;
+    isFull() {
+        return connections.size() == CdmaCallTracker.MAX_CONNECTIONS_PER_CALL;
     }
 
-    //***** Called from CallTracker
+    //***** Called from CdmaCallTracker
 
 
-    /** 
+    /**
      * Called when this Call is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
      * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         for (int i = 0, s = connections.size()
                 ; i < s; i++
         ) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
+            CdmaConnection cn = (CdmaConnection)connections.get(i);
 
             cn.onHangupLocal();
         }
     }
-    
+
     /**
      * Called when it's time to clean up disconnected Connection objects
      */
-    void
-    clearDisconnected()
-    {
+   void clearDisconnected() {
         for (int i = connections.size() - 1 ; i >= 0 ; i--) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
-            
+        CdmaConnection cn = (CdmaConnection)connections.get(i);
+
             if (cn.getState() == State.DISCONNECTED) {
                 connections.remove(i);
             }
-        }    
+        }
 
         if (connections.size() == 0) {
             state = State.IDLE;
         }
     }
 }
-
diff --git a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
similarity index 69%
copy from telephony/java/com/android/internal/telephony/gsm/CallTracker.java
copy to telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index 2d716bb..a1d362f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -14,30 +14,24 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony.cdma;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_EDGE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_GPRS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UMTS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UNKNOWN;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RegistrantList;
-import android.os.SystemProperties;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
-import android.telephony.gsm.GsmCellLocation;
-import android.util.EventLog;
 import android.util.Log;
 
-import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CallTracker;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -45,95 +39,108 @@
 /**
  * {@hide}
  */
-public final class CallTracker extends Handler
-{
-    static final String LOG_TAG = "GSM";
+public final class CdmaCallTracker extends CallTracker {
+    static final String LOG_TAG = "CDMA";
+
     private static final boolean REPEAT_POLLING = false;
 
     private static final boolean DBG_POLL = false;
 
     //***** Constants
 
-    static final int POLL_DELAY_MSEC = 250;
-    static final int MAX_CONNECTIONS = 7;   // only 7 connections allowed in GSM
-    static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call
+    static final int MAX_CONNECTIONS = 1;   // only 1 connection allowed in CDMA
+    static final int MAX_CONNECTIONS_PER_CALL = 1; // only 1 connection allowed per call
 
     //***** Instance Variables
 
-    GSMConnection connections[] = new GSMConnection[MAX_CONNECTIONS];
+    CdmaConnection connections[] = new CdmaConnection[MAX_CONNECTIONS];
     RegistrantList voiceCallEndedRegistrants = new RegistrantList();
     RegistrantList voiceCallStartedRegistrants = new RegistrantList();
 
 
     // connections dropped durin last poll
-    ArrayList<GSMConnection> droppedDuringPoll
-        = new ArrayList<GSMConnection>(MAX_CONNECTIONS);
+    ArrayList<CdmaConnection> droppedDuringPoll
+        = new ArrayList<CdmaConnection>(MAX_CONNECTIONS);
 
-    GSMCall ringingCall = new GSMCall(this);
-            // A call that is ringing or (call) waiting
-    GSMCall foregroundCall = new GSMCall(this);
-    GSMCall backgroundCall = new GSMCall(this);
+    CdmaCall ringingCall = new CdmaCall(this);
+    // A call that is ringing or (call) waiting
+    CdmaCall foregroundCall = new CdmaCall(this);
+    CdmaCall backgroundCall = new CdmaCall(this);
 
-    GSMConnection pendingMO;
+    CdmaConnection pendingMO;
     boolean hangupPendingMO;
 
-    GSMPhone phone;
-    CommandsInterface cm;
+    CDMAPhone phone;
+
     boolean desiredMute = false;    // false = mute off
 
     Phone.State state = Phone.State.IDLE;
 
-    int pendingOperations;
-    boolean needsPoll;
-    Message lastRelevantPoll;
+
+//    boolean needsPoll;
+
 
 
     //***** Events
 
-    static final int EVENT_POLL_CALLS_RESULT    = 1;
-    static final int EVENT_CALL_STATE_CHANGE    = 2;
-    static final int EVENT_REPOLL_AFTER_DELAY   = 3;
-    static final int EVENT_OPERATION_COMPLETE     = 4;
-    static final int EVENT_GET_LAST_CALL_FAIL_CAUSE = 5;
-
-    static final int EVENT_SWITCH_RESULT        = 8;
-    static final int EVENT_RADIO_AVAILABLE       = 9;
-    static final int EVENT_RADIO_NOT_AVAILABLE       = 10;
-    static final int EVENT_CONFERENCE_RESULT    = 11;
-    static final int EVENT_SEPARATE_RESULT      = 12;
-    static final int EVENT_ECT_RESULT           = 13;
-
     //***** Constructors
-
-    CallTracker (GSMPhone phone)
-    {
+    CdmaCallTracker(CDMAPhone phone) {
         this.phone = phone;
         cm = phone.mCM;
-
         cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
-
         cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
         cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
     }
 
+    public void dispose() {
+        cm.unregisterForCallStateChanged(this);
+        cm.unregisterForOn(this);
+        cm.unregisterForNotAvailable(this);
+
+        for(CdmaConnection c : connections) {
+            try {
+                if(c != null) hangup(c);
+            } catch (CallStateException ex) {
+                Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+            }
+        }
+
+        try {
+            if(pendingMO != null) hangup(pendingMO);
+        } catch (CallStateException ex) {
+            Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+        }
+
+        clearDisconnected();
+
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "CdmaCallTracker finalized");
+    }
+
     //***** Instance Methods
 
     //***** Public Methods
-    public void registerForVoiceCallStarted(Handler h, int what, Object obj)
-    {
+    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallStartedRegistrants.add(r);
     }
+    public void unregisterForVoiceCallStarted(Handler h) {
+        voiceCallStartedRegistrants.remove(h);
+    }
 
-    public void registerForVoiceCallEnded(Handler h, int what, Object obj)
-    {
+    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallEndedRegistrants.add(r);
     }
 
+    public void unregisterForVoiceCallEnded(Handler h) {
+        voiceCallEndedRegistrants.remove(h);
+    }
+
     private void
-    fakeHoldForegroundBeforeDial()
-    {
+    fakeHoldForegroundBeforeDial() {
         List<Connection> connCopy;
 
         // We need to make a copy here, since fakeHoldBeforeDial()
@@ -141,7 +148,7 @@
         connCopy = (List<Connection>) foregroundCall.connections.clone();
 
         for (int i = 0, s = connCopy.size() ; i < s ; i++) {
-            GSMConnection conn = (GSMConnection)connCopy.get(i);
+            CdmaConnection conn = (CdmaConnection)connCopy.get(i);
 
             conn.fakeHoldBeforeDial();
         }
@@ -162,7 +169,7 @@
         // The new call must be assigned to the foreground call.
         // That call must be idle, so place anything that's
         // there on hold
-        if (foregroundCall.getState() == Call.State.ACTIVE) {
+        if (foregroundCall.getState() == CdmaCall.State.ACTIVE) {
             // this will probably be done by the radio anyway
             // but the dial might fail before this happens
             // and we need to make sure the foreground call is clear
@@ -176,12 +183,12 @@
             fakeHoldForegroundBeforeDial();
         }
 
-        if (foregroundCall.getState() != Call.State.IDLE) {
+        if (foregroundCall.getState() != CdmaCall.State.IDLE) {
             //we should have failed in !canDial() above before we get here
             throw new CallStateException("cannot dial in current state");
         }
 
-        pendingMO = new GSMConnection(phone.getContext(), dialString, this, foregroundCall);
+        pendingMO = new CdmaConnection(phone.getContext(), dialString, this, foregroundCall);
         hangupPendingMO = false;
 
         if (pendingMO.address == null || pendingMO.address.length() == 0
@@ -208,24 +215,22 @@
 
 
     Connection
-    dial (String dialString) throws CallStateException
-    {
+    dial (String dialString) throws CallStateException {
         return dial(dialString, CommandsInterface.CLIR_DEFAULT);
     }
 
     void
-    acceptCall () throws CallStateException
-    {
+    acceptCall () throws CallStateException {
         // FIXME if SWITCH fails, should retry with ANSWER
         // in case the active/holding call disappeared and this
         // is no longer call waiting
 
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == CdmaCall.State.INCOMING) {
             Log.i("phone", "acceptCall: incoming...");
             // Always unmute when answering a new call
             setMute(false);
             cm.acceptCall(obtainCompleteMessage());
-        } else if (ringingCall.getState() == Call.State.WAITING) {
+        } else if (ringingCall.getState() == CdmaCall.State.WAITING) {
             setMute(false);
             switchWaitingOrHoldingAndActive();
         } else {
@@ -234,8 +239,7 @@
     }
 
     void
-    rejectCall () throws CallStateException
-    {
+    rejectCall () throws CallStateException {
         // AT+CHLD=0 means "release held or UDUB"
         // so if the phone isn't ringing, this could hang up held
         if (ringingCall.getState().isRinging()) {
@@ -248,29 +252,26 @@
     void
     switchWaitingOrHoldingAndActive() throws CallStateException {
         // Should we bother with this check?
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == CdmaCall.State.INCOMING) {
             throw new CallStateException("cannot be in the incoming state");
         } else {
-            cm.switchWaitingOrHoldingAndActive(
-                    obtainCompleteMessage(EVENT_SWITCH_RESULT));
+            cm.sendCDMAFeatureCode("", obtainCompleteMessage(EVENT_SWITCH_RESULT));
         }
     }
 
     void
-    conference() throws CallStateException
-    {
-        cm.conference(obtainCompleteMessage(EVENT_CONFERENCE_RESULT));
+    conference() throws CallStateException {
+        // three way calls in CDMA will be handled by feature codes
+        Log.e(LOG_TAG, "conference: not possible in CDMA");
     }
 
     void
-    explicitCallTransfer() throws CallStateException
-    {
+    explicitCallTransfer() throws CallStateException {
         cm.explicitCallTransfer(obtainCompleteMessage(EVENT_ECT_RESULT));
     }
 
     void
-    clearDisconnected()
-    {
+    clearDisconnected() {
         internalClearDisconnected();
 
         updatePhoneState();
@@ -278,17 +279,15 @@
     }
 
     boolean
-    canConference()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING
+    canConference() {
+        return foregroundCall.getState() == CdmaCall.State.ACTIVE
+                && backgroundCall.getState() == CdmaCall.State.HOLDING
                 && !backgroundCall.isFull()
                 && !foregroundCall.isFull();
     }
 
     boolean
-    canDial()
-    {
+    canDial() {
         boolean ret;
         int serviceState = phone.getServiceState().getState();
 
@@ -302,42 +301,26 @@
     }
 
     boolean
-    canTransfer()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING;
+    canTransfer() {
+        Log.e(LOG_TAG, "canTransfer: not possible in CDMA");
+        return false;
     }
 
     //***** Private Instance Methods
 
     private void
-    internalClearDisconnected()
-    {
+    internalClearDisconnected() {
         ringingCall.clearDisconnected();
         foregroundCall.clearDisconnected();
         backgroundCall.clearDisconnected();
     }
 
     /**
-     * @return true if we're idle or there's a call to getCurrentCalls() pending
-     * but nothing else
-     */
-    private boolean
-    checkNoOperationsPending()
-    {
-        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
-                pendingOperations);
-        return pendingOperations == 0;
-    }
-
-
-    /**
      * Obtain a message to use for signalling "invoke getCurrentCalls() when
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage()
-    {
+    obtainCompleteMessage() {
         return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
     }
 
@@ -346,8 +329,7 @@
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage(int what)
-    {
+    obtainCompleteMessage(int what) {
         pendingOperations++;
         lastRelevantPoll = null;
         needsPoll = true;
@@ -358,26 +340,8 @@
         return obtainMessage(what);
     }
 
-    /**
-     * Obtain a complete message that indicates that this operation
-     * does not require polling of getCurrentCalls(). However, if other
-     * operations that do need getCurrentCalls() are pending or are
-     * scheduled while this operation is pending, the invocatoin
-     * of getCurrentCalls() will be postponed until this
-     * operation is also complete.
-     */
-    private Message
-    obtainNoPollCompleteMessage(int what)
-    {
-        pendingOperations++;
-        lastRelevantPoll = null;
-        return obtainMessage(what);
-    }
-
-
     private void
-    operationComplete()
-    {
+    operationComplete() {
         pendingOperations--;
 
         if (DBG_POLL) log("operationComplete: pendingOperations=" +
@@ -388,42 +352,15 @@
             cm.getCurrentCalls(lastRelevantPoll);
         } else if (pendingOperations < 0) {
             // this should never happen
-            Log.e(LOG_TAG,"CallTracker.pendingOperations < 0");
+            Log.e(LOG_TAG,"CdmaCallTracker.pendingOperations < 0");
             pendingOperations = 0;
         }
     }
 
-    private void
-    pollCallsWhenSafe()
-    {
-        needsPoll = true;
 
-        if (checkNoOperationsPending()) {
-            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
-            cm.getCurrentCalls(lastRelevantPoll);
-        }
-    }
 
     private void
-    pollCallsAfterDelay()
-    {
-        Message msg = obtainMessage();
-
-        msg.what = EVENT_REPOLL_AFTER_DELAY;
-        sendMessageDelayed(msg, POLL_DELAY_MSEC);
-    }
-
-    private boolean
-    isCommandExceptionRadioNotAvailable(Throwable e)
-    {
-        return e != null && e instanceof CommandException
-                && ((CommandException)e).getCommandError()
-                        == CommandException.Error.RADIO_NOT_AVAILABLE;
-    }
-
-    private void
-    updatePhoneState()
-    {
+    updatePhoneState() {
         Phone.State oldState = state;
 
         if (ringingCall.isRinging()) {
@@ -448,9 +385,10 @@
         }
     }
 
-    private void
-    handlePollCalls(AsyncResult ar)
-    {
+    // ***** Overwritten from CallTracker
+
+    protected void
+    handlePollCalls(AsyncResult ar) {
         List polledCalls;
 
         if (ar.exception == null) {
@@ -474,7 +412,7 @@
 
         for (int i = 0, curDC = 0, dcSize = polledCalls.size()
                 ; i < connections.length; i++) {
-            GSMConnection conn = connections[i];
+            CdmaConnection conn = connections[i];
             DriverCall dc = null;
 
             // polledCall list is sparse
@@ -519,7 +457,7 @@
                         return;
                     }
                 } else {
-                    connections[i] = new GSMConnection(phone.getContext(), dc, this, i);
+                    connections[i] = new CdmaConnection(phone.getContext(), dc, this, i);
 
                     // it's a ringing call
                     if (connections[i].getCall() == ringingCall) {
@@ -549,14 +487,14 @@
                 // tracking.
                 droppedDuringPoll.add(conn);
                 // Dropped connections are removed from the CallTracker
-                // list but kept in the GSMCall list
+                // list but kept in the Call list
                 connections[i] = null;
             } else if (conn != null && dc != null && !conn.compareTo(dc)) {
                 // Connection in CLCC response does not match what
                 // we were tracking. Assume dropped call and new call
 
                 droppedDuringPoll.add(conn);
-                connections[i] = new GSMConnection (phone.getContext(), dc, this, i);
+                connections[i] = new CdmaConnection (phone.getContext(), dc, this, i);
 
                 if (connections[i].getCall() == ringingCall) {
                     newRinging = connections[i];
@@ -608,7 +546,7 @@
         // cases from the "dropped during poll" list
         // These cases need no "last call fail" reason
         for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) {
-            GSMConnection conn = droppedDuringPoll.get(i);
+            CdmaConnection conn = droppedDuringPoll.get(i);
 
             if (conn.isIncoming() && conn.getConnectTime() == 0) {
                 // Missed or rejected call
@@ -629,8 +567,7 @@
                 // Local hangup
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.LOCAL);
-            } else if (conn.cause ==
-                    Connection.DisconnectCause.INVALID_NUMBER) {
+            } else if (conn.cause == Connection.DisconnectCause.INVALID_NUMBER) {
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
             }
@@ -668,59 +605,12 @@
         //dumpState();
     }
 
-    private void
-    handleRadioAvailable()
-    {
-        pollCallsWhenSafe();
-    }
-
-    private void
-    handleRadioNotAvailable()
-    {
-        // handlePollCalls will clear out its
-        // call list when it gets the CommandException
-        // error result from this
-        pollCallsWhenSafe();
-    }
-
-    private void
-    dumpState()
-    {
-        List l;
-
-        Log.i(LOG_TAG,"Phone State:" + state);
-
-        Log.i(LOG_TAG,"Ringing call: " + ringingCall.toString());
-
-        l = ringingCall.getConnections();
-        for (int i = 0, s = l.size(); i < s; i++) {
-            Log.i(LOG_TAG,l.get(i).toString());
-        }
-
-        Log.i(LOG_TAG,"Foreground call: " + foregroundCall.toString());
-
-        l = foregroundCall.getConnections();
-        for (int i = 0, s = l.size(); i < s; i++) {
-            Log.i(LOG_TAG,l.get(i).toString());
-        }
-
-        Log.i(LOG_TAG,"Background call: " + backgroundCall.toString());
-
-        l = backgroundCall.getConnections();
-        for (int i = 0, s = l.size(); i < s; i++) {
-            Log.i(LOG_TAG,l.get(i).toString());
-        }
-
-    }
-
-    //***** Called from GSMConnection
-
+    //***** Called from CdmaConnection
     /*package*/ void
-    hangup (GSMConnection conn) throws CallStateException
-    {
+    hangup (CdmaConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("CdmaConnection " + conn
+                                    + "does not belong to CdmaCallTracker " + this);
         }
 
         if (conn == pendingMO) {
@@ -731,11 +621,11 @@
             hangupPendingMO = true;
         } else {
             try {
-                cm.hangupConnection (conn.getGSMIndex(), obtainCompleteMessage());
+                cm.hangupConnection (conn.getCDMAIndex(), obtainCompleteMessage());
             } catch (CallStateException ex) {
                 // Ignore "connection not found"
                 // Call may have hung up already
-                Log.w(LOG_TAG,"CallTracker WARN: hangup() on absent connection "
+                Log.w(LOG_TAG,"CdmaCallTracker WARN: hangup() on absent connection "
                                 + conn);
             }
         }
@@ -744,44 +634,40 @@
     }
 
     /*package*/ void
-    separate (GSMConnection conn) throws CallStateException
-    {
+    separate (CdmaConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("CdmaConnection " + conn
+                                    + "does not belong to CdmaCallTracker " + this);
         }
         try {
-            cm.separateConnection (conn.getGSMIndex(),
+            cm.separateConnection (conn.getCDMAIndex(),
                 obtainCompleteMessage(EVENT_SEPARATE_RESULT));
         } catch (CallStateException ex) {
             // Ignore "connection not found"
             // Call may have hung up already
-            Log.w(LOG_TAG,"CallTracker WARN: separate() on absent connection "
+            Log.w(LOG_TAG,"CdmaCallTracker WARN: separate() on absent connection "
                           + conn);
         }
     }
 
-    //***** Called from GSMPhone
+    //***** Called from CDMAPhone
 
     /*package*/ void
-    setMute(boolean mute)
-    {
+    setMute(boolean mute) {
         desiredMute = mute;
         cm.setMute(desiredMute, null);
     }
 
     /*package*/ boolean
-    getMute()
-    {
+    getMute() {
         return desiredMute;
     }
 
 
-    //***** Called from GSMCall
+    //***** Called from CdmaCall
 
     /* package */ void
-    hangup (GSMCall call) throws CallStateException
-    {
+    hangup (CdmaCall call) throws CallStateException {
         if (call.getConnections().size() == 0) {
             throw new CallStateException("no connections in call");
         }
@@ -794,7 +680,7 @@
                 if (Phone.DEBUG_PHONE) {
                     log("(foregnd) hangup dialing or alerting...");
                 }
-                hangup((GSMConnection)(call.getConnections().get(0)));
+                hangup((CdmaConnection)(call.getConnections().get(0)));
             } else {
                 hangupForegroundResumeBackground();
             }
@@ -808,8 +694,8 @@
                 hangupWaitingOrBackground();
             }
         } else {
-            throw new RuntimeException ("Call " + call +
-                    "does not belong to CallTracker " + this);
+            throw new RuntimeException ("CdmaCall " + call +
+                    "does not belong to CdmaCallTracker " + this);
         }
 
         call.onHangupLocal();
@@ -827,12 +713,12 @@
         cm.hangupForegroundResumeBackground(obtainCompleteMessage());
     }
 
-    void hangupConnectionByIndex(GSMCall call, int index)
+    void hangupConnectionByIndex(CdmaCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
-            if (cn.getGSMIndex() == index) {
+            CdmaConnection cn = (CdmaConnection)call.connections.get(i);
+            if (cn.getCDMAIndex() == index) {
                 cm.hangupConnection(index, obtainCompleteMessage());
                 return;
             }
@@ -841,12 +727,12 @@
         throw new CallStateException("no gsm index found");
     }
 
-    void hangupAllConnections(GSMCall call) throws CallStateException{
+    void hangupAllConnections(CdmaCall call) throws CallStateException{
         try {
             int count = call.connections.size();
             for (int i = 0; i < count; i++) {
-                GSMConnection cn = (GSMConnection)call.connections.get(i);
-                cm.hangupConnection(cn.getGSMIndex(), obtainCompleteMessage());
+                CdmaConnection cn = (CdmaConnection)call.connections.get(i);
+                cm.hangupConnection(cn.getCDMAIndex(), obtainCompleteMessage());
             }
         } catch (CallStateException ex) {
             Log.e(LOG_TAG, "hangupConnectionByIndex caught " + ex);
@@ -854,12 +740,12 @@
     }
 
     /* package */
-    GSMConnection getConnectionByIndex(GSMCall call, int index)
+    CdmaConnection getConnectionByIndex(CdmaCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
-            if (cn.getGSMIndex() == index) {
+            CdmaConnection cn = (CdmaConnection)call.connections.get(i);
+            if (cn.getCDMAIndex() == index) {
                 return cn;
             }
         }
@@ -881,24 +767,32 @@
         return Phone.SuppService.UNKNOWN;
     }
 
+    private void handleRadioNotAvailable() {
+        // handlePollCalls will clear out its
+        // call list when it gets the CommandException
+        // error result from this
+        pollCallsWhenSafe();
+    }
+
     //****** Overridden from Handler
 
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
 
         switch (msg.what) {
-            case EVENT_POLL_CALLS_RESULT:
+            case EVENT_POLL_CALLS_RESULT:{
+                Log.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
                 ar = (AsyncResult)msg.obj;
 
-                if (msg == lastRelevantPoll) {
-                    if (DBG_POLL) log(
+                if(msg == lastRelevantPoll) {
+                    if(DBG_POLL) log(
                             "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
                     needsPoll = false;
                     lastRelevantPoll = null;
                     handlePollCalls((AsyncResult)msg.obj);
                 }
+            }
             break;
 
             case EVENT_OPERATION_COMPLETE:
@@ -907,14 +801,8 @@
             break;
 
             case EVENT_SWITCH_RESULT:
-            case EVENT_CONFERENCE_RESULT:
-            case EVENT_SEPARATE_RESULT:
-            case EVENT_ECT_RESULT:
-                ar = (AsyncResult)msg.obj;
-                if (ar.exception != null) {
-                    phone.notifySuppServiceFailed(getFailedService(msg.what));
-                }
-                operationComplete();
+                  ar = (AsyncResult)msg.obj;
+                  operationComplete();
             break;
 
             case EVENT_GET_LAST_CALL_FAIL_CAUSE:
@@ -932,27 +820,11 @@
                 } else {
                     causeCode = ((int[])ar.result)[0];
                 }
-                // Log the causeCode if its not normal
-                if (causeCode == CallFailCause.NO_CIRCUIT_AVAIL ||
-                    causeCode == CallFailCause.TEMPORARY_FAILURE ||
-                    causeCode == CallFailCause.SWITCHING_CONGESTION ||
-                    causeCode == CallFailCause.CHANNEL_NOT_AVAIL ||
-                    causeCode == CallFailCause.QOS_NOT_AVAIL ||
-                    causeCode == CallFailCause.BEARER_NOT_AVAIL ||
-                    causeCode == CallFailCause.ERROR_UNSPECIFIED) {
-                    int cid = -1;
-                    GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                    if (loc != null) cid = loc.getCid();
-
-                    EventLog.List val = new EventLog.List(causeCode, cid,
-                        TelephonyManager.getDefault().getNetworkType());
-                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CALL_DROP, val);
-                }
 
                 for (int i = 0, s =  droppedDuringPoll.size()
                         ; i < s ; i++
                 ) {
-                    GSMConnection conn = droppedDuringPoll.get(i);
+                    CdmaConnection conn = droppedDuringPoll.get(i);
 
                     conn.onRemoteDisconnect(causeCode);
                 }
@@ -963,7 +835,6 @@
                 droppedDuringPoll.clear();
             break;
 
-            case EVENT_REPOLL_AFTER_DELAY:
             case EVENT_CALL_STATE_CHANGE:
                 pollCallsWhenSafe();
             break;
@@ -975,10 +846,15 @@
             case EVENT_RADIO_NOT_AVAILABLE:
                 handleRadioNotAvailable();
             break;
+
+            default:{
+             throw new RuntimeException("unexpected event not handled");
+            }
         }
     }
 
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[CallTracker] " + msg);
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[CdmaCallTracker] " + msg);
     }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
similarity index 76%
copy from telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
copy to telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 4777892..cdad4a7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -14,41 +14,42 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+package com.android.internal.telephony.cdma;
 
+import com.android.internal.telephony.*;
 import android.content.Context;
+import android.os.AsyncResult;
 import android.os.Handler;
-import android.os.PowerManager;
-import android.os.Registrant;
 import android.os.Looper;
 import android.os.Message;
-import android.os.AsyncResult;
+import android.os.PowerManager;
+import android.os.Registrant;
 import android.os.SystemClock;
-import android.util.Log;
 import android.util.Config;
+import android.util.Log;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 
+
 /**
  * {@hide}
  */
-public class GSMConnection extends Connection {
-    static final String LOG_TAG = "GSM";
+public class CdmaConnection extends Connection {
+    static final String LOG_TAG = "CDMA";
 
     //***** Instance Variables
 
-    CallTracker owner;
-    GSMCall parent;
+    CdmaCallTracker owner;
+    CdmaCall parent;
 
-    String address;     // MAY BE NULL!!!
+
+    String address;             // MAY BE NULL!!!
     String dialString;          // outgoing calls only
-    String postDialString;      // outgoing calls only    
+    String postDialString;      // outgoing calls only
     boolean isIncoming;
-    boolean disconnected; 
+    boolean disconnected;
 
-    int index;          // index in CallTracker.connections[], -1 if unassigned
-                        // The GSM index is 1 + this
+    int index;          // index in CdmaCallTracker.connections[], -1 if unassigned
 
     /*
      * These time/timespan values are based on System.currentTimeMillis(),
@@ -65,7 +66,7 @@
      */
     long connectTimeReal;
     long duration;
-    long holdingStartTime;  // The time when the Connection last transitioned 
+    long holdingStartTime;  // The time when the Connection last transitioned
                             // into HOLDING
 
     int nextPostDialChar;       // index into postDialString
@@ -95,8 +96,8 @@
         MyHandler(Looper l) {super(l);}
 
         public void
-        handleMessage(Message msg)
-        {
+        handleMessage(Message msg) {
+
             switch (msg.what) {
                 case EVENT_NEXT_POST_DIAL:
                 case EVENT_DTMF_DONE:
@@ -114,8 +115,7 @@
 
     /** This is probably an MT call that we first saw in a CLCC response */
     /*package*/
-    GSMConnection (Context context, DriverCall dc, CallTracker ct, int index)
-    {
+    CdmaConnection (Context context, DriverCall dc, CdmaCallTracker ct, int index) {
         createWakeLock(context);
         acquireWakeLock();
 
@@ -136,11 +136,10 @@
 
     /** This is an MO call, created when dialing */
     /*package*/
-    GSMConnection (Context context, String dialString, CallTracker ct, GSMCall parent)
-    {
+    CdmaConnection (Context context, String dialString, CdmaCallTracker ct, CdmaCall parent) {
         createWakeLock(context);
         acquireWakeLock();
-
+		
         owner = ct;
         h = new MyHandler(owner.getLooper());
 
@@ -155,18 +154,19 @@
         createTime = System.currentTimeMillis();
 
         this.parent = parent;
-        parent.attachFake(this, Call.State.DIALING);
+        parent.attachFake(this, CdmaCall.State.DIALING);
     }
-    
+
+    public void dispose() {
+    }
+
     static boolean
-    equalsHandlesNulls (Object a, Object b)
-    {
+    equalsHandlesNulls (Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
 
     /*package*/ boolean
-    compareTo(DriverCall c)
-    {
+    compareTo(DriverCall c) {
         // On mobile originated (MO) calls, the phone number may have changed
         // due to a SIM Toolkit call control modification.
         //
@@ -178,43 +178,35 @@
         // no control over when they begin, so we might as well
 
         String cAddress = PhoneNumberUtils.stringFromStringAndTOA(c.number, c.TOA);
-        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress); 
+        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return (isIncoming ? "incoming" : "outgoing");
     }
 
-    public String getAddress()
-    {
-        return address; 
+    public String getAddress() {
+        return address;
     }
 
-
-    public Call getCall()
-    {
+    public CdmaCall getCall() {
         return parent;
     }
 
-    public long getCreateTime()
-    {
+    public long getCreateTime() {
         return createTime;
     }
 
-    public long getConnectTime()
-    {
+    public long getConnectTime() {
         return connectTime;
     }
 
-    public long getDisconnectTime()
-    {
+    public long getDisconnectTime() {
         return disconnectTime;
     }
 
-    public long getDurationMillis()
-    {
+    public long getDurationMillis() {
         if (connectTimeReal == 0) {
             return 0;
         } else if (duration == 0) {
@@ -224,9 +216,8 @@
         }
     }
 
-    public long getHoldDurationMillis()
-    {
-        if (getState() != Call.State.HOLDING) {
+    public long getHoldDurationMillis() {
+        if (getState() != CdmaCall.State.HOLDING) {
             // If not holding, return 0
             return 0;
         } else {
@@ -234,52 +225,45 @@
         }
     }
 
-    public DisconnectCause getDisconnectCause()
-    {
+    public DisconnectCause getDisconnectCause() {
         return cause;
     }
 
-    public boolean isIncoming()
-    {
+    public boolean isIncoming() {
         return isIncoming;
     }
 
-    public Call.State getState()
-    {
+    public CdmaCall.State getState() {
         if (disconnected) {
-            return Call.State.DISCONNECTED;
-        } else {   
+            return CdmaCall.State.DISCONNECTED;
+        } else {
             return super.getState();
         }
     }
 
-    public void hangup() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void hangup() throws CallStateException {
+        if (!disconnected) {
             owner.hangup(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public void separate() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void separate() throws CallStateException {
+        if (!disconnected) {
             owner.separate(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public PostDialState getPostDialState()
-    {
+    public PostDialState getPostDialState() {
         return postDialState;
     }
 
-    public void proceedAfterWaitChar()
-    {
+    public void proceedAfterWaitChar() {
         if (postDialState != PostDialState.WAIT) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "CdmaConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WAIT but was " + postDialState);
             return;
         }
@@ -288,10 +272,10 @@
 
         processNextPostDialChar();
     }
-    
+
     public void proceedAfterWildChar(String str) {
         if (postDialState != PostDialState.WILD) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "CdmaConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WILD but was " + postDialState);
             return;
         }
@@ -328,81 +312,51 @@
             postDialString = buf.toString();
             nextPostDialChar = 0;
             if (Phone.DEBUG_PHONE) {
-                log("proceedAfterWildChar: new postDialString is " + 
+                log("proceedAfterWildChar: new postDialString is " +
                         postDialString);
             }
 
             processNextPostDialChar();
         }
     }
-    
-    public void cancelPostDial()
-    {
+
+    public void cancelPostDial() {
         setPostDialState(PostDialState.CANCELLED);
     }
 
-    /** 
+    /**
      * Called when this Connection is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
-     * but no response has yet been received so update() has not yet been called 
+     * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         cause = DisconnectCause.LOCAL;
     }
 
     DisconnectCause
-    disconnectCauseFromCode(int causeCode)
-    {
+    disconnectCauseFromCode(int causeCode) {
         /**
          * See 22.001 Annex F.4 for mapping of cause codes
          * to local tones
          */
-    
+
         switch (causeCode) {
             case CallFailCause.USER_BUSY:
                 return DisconnectCause.BUSY;
-
-            case CallFailCause.NO_CIRCUIT_AVAIL:
-            case CallFailCause.TEMPORARY_FAILURE:
-            case CallFailCause.SWITCHING_CONGESTION:
-            case CallFailCause.CHANNEL_NOT_AVAIL:
-            case CallFailCause.QOS_NOT_AVAIL:
-            case CallFailCause.BEARER_NOT_AVAIL:
-                return DisconnectCause.CONGESTION;
-
-            case CallFailCause.ACM_LIMIT_EXCEEDED:
-                return DisconnectCause.LIMIT_EXCEEDED;
-
-            case CallFailCause.CALL_BARRED:
-                return DisconnectCause.CALL_BARRED;
-
-            case CallFailCause.FDN_BLOCKED:
-                return DisconnectCause.FDN_BLOCKED;
-
             case CallFailCause.ERROR_UNSPECIFIED:
-            case CallFailCause.NORMAL_CLEARING: 
+            case CallFailCause.NORMAL_CLEARING:
             default:
-                GSMPhone phone = owner.phone;
+                CDMAPhone phone = owner.phone;
                 int serviceState = phone.getServiceState().getState();
                 if (serviceState == ServiceState.STATE_POWER_OFF) {
                     return DisconnectCause.POWER_OFF;
                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
                         || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
                     return DisconnectCause.OUT_OF_SERVICE;
-                } else if (phone.getSimCard().getState() != GsmSimCard.State.READY) {
-                    return DisconnectCause.SIM_ERROR;
-                } else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
-                    if (phone.mSST.rs.isCsRestricted()) {
-                        return DisconnectCause.CS_RESTRICTED; 
-                    } else if (phone.mSST.rs.isCsEmergencyRestricted()) {
-                        return DisconnectCause.CS_RESTRICTED_EMERGENCY;
-                    } else if (phone.mSST.rs.isCsNormalRestricted()) {
-                        return DisconnectCause.CS_RESTRICTED_NORMAL;
-                    } else {
-                        return DisconnectCause.NORMAL;
-                    }
+                } else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
+                        && phone.getIccCard().getState() != RuimCard.State.READY) {
+                    return DisconnectCause.ICC_ERROR;
                 } else {
                     return DisconnectCause.NORMAL;
                 }
@@ -410,31 +364,29 @@
     }
 
     /*package*/ void
-    onRemoteDisconnect(int causeCode)
-    {
+    onRemoteDisconnect(int causeCode) {
         onDisconnect(disconnectCauseFromCode(causeCode));
     }
 
     /** Called when the radio indicates the connection has been disconnected */
     /*package*/ void
-    onDisconnect(DisconnectCause cause)
-    {
+    onDisconnect(DisconnectCause cause) {
         this.cause = cause;
-        
-        if (!disconnected) {        
+
+        if (!disconnected) {
             index = -1;
-            
+
             disconnectTime = System.currentTimeMillis();
             duration = SystemClock.elapsedRealtime() - connectTimeReal;
             disconnected = true;
 
             if (Config.LOGD) Log.d(LOG_TAG,
-                    "[GSMConn] onDisconnect: cause=" + cause);
+                    "[CDMAConn] onDisconnect: cause=" + cause);
 
             owner.phone.notifyDisconnect(this);
 
             if (parent != null) {
-                parent.connectionDisconnected(this);            
+                parent.connectionDisconnected(this);
             }
         }
         releaseWakeLock();
@@ -443,10 +395,10 @@
     // Returns true if state has changed, false if nothing changed
     /*package*/ boolean
     update (DriverCall dc) {
-        GSMCall newParent;
+        CdmaCall newParent;
         boolean changed = false;
         boolean wasConnectingInOrOut = isConnectingInOrOut();
-        boolean wasHolding = (getState() == Call.State.HOLDING);
+        boolean wasHolding = (getState() == CdmaCall.State.HOLDING);
 
         newParent = parentFromDCState(dc.state);
 
@@ -484,7 +436,7 @@
             onConnectedInOrOut();
         }
 
-        if (changed && !wasHolding && (getState() == Call.State.HOLDING)) {
+        if (changed && !wasHolding && (getState() == CdmaCall.State.HOLDING)) {
             // We've transitioned into HOLDING
             onStartedHolding();
         }
@@ -499,24 +451,23 @@
      * HOLDING in the backgroundCall
      */
     void
-    fakeHoldBeforeDial()
-    {
+    fakeHoldBeforeDial() {
         if (parent != null) {
             parent.detach(this);
         }
 
         parent = owner.backgroundCall;
-        parent.attachFake(this, Call.State.HOLDING);
+        parent.attachFake(this, CdmaCall.State.HOLDING);
 
         onStartedHolding();
     }
 
     /*package*/ int
-    getGSMIndex() throws CallStateException {
+    getCDMAIndex() throws CallStateException {
         if (index >= 0) {
             return index + 1;
         } else {
-            throw new CallStateException ("GSM index not yet assigned");
+            throw new CallStateException ("CDMA connection index not assigned");
         }
     }
 
@@ -552,28 +503,27 @@
      * should be ignored
      */
     private boolean
-    processPostDialChar(char c)
-    {
+    processPostDialChar(char c) {
         if (PhoneNumberUtils.is12Key(c)) {
             owner.cm.sendDtmf(c, h.obtainMessage(EVENT_DTMF_DONE));
         } else if (c == PhoneNumberUtils.PAUSE) {
             // From TS 22.101:
 
-            // "The first occurrence of the "DTMF Control Digits Separator" 
-            //  shall be used by the ME to distinguish between the addressing 
+            // "The first occurrence of the "DTMF Control Digits Separator"
+            //  shall be used by the ME to distinguish between the addressing
             //  digits (i.e. the phone number) and the DTMF digits...."
 
             if (nextPostDialChar == 1) {
                 // The first occurrence.
                 // We don't need to pause here, but wait for just a bit anyway
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_FIRST_MILLIS);
             } else {
                 // It continues...
-                // "Upon subsequent occurrences of the separator, the UE shall 
-                //  pause again for 3 seconds (\u00B1 20 %) before sending any 
+                // "Upon subsequent occurrences of the separator, the UE shall
+                //  pause again for 3 seconds (\u00B1 20 %) before sending any
                 //  further DTMF digits."
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_MILLIS);
             }
         } else if (c == PhoneNumberUtils.WAIT) {
@@ -588,9 +538,8 @@
     }
 
     public String
-    getRemainingPostDialString()
-    {
-        if (postDialState == PostDialState.CANCELLED 
+    getRemainingPostDialString() {
+        if (postDialState == PostDialState.CANCELLED
             || postDialState == PostDialState.COMPLETE
             || postDialString == null
             || postDialString.length() <= nextPostDialChar
@@ -611,19 +560,18 @@
          * and or onConnectedInOrOut.
          */
         if (mPartialWakeLock.isHeld()) {
-            Log.e(LOG_TAG, "[GSMConn] UNEXPECTED; mPartialWakeLock is held when finalizing.");
+            Log.e(LOG_TAG, "[CdmaConn] UNEXPECTED; mPartialWakeLock is held when finalizing.");
         }
         releaseWakeLock();
     }
 
     private void
-    processNextPostDialChar()
-    {
+    processNextPostDialChar() {
         char c = 0;
         Registrant postDialHandler;
 
         if (postDialState == PostDialState.CANCELLED) {
-            //Log.v("GSM", "##### processNextPostDialChar: postDialState == CANCELLED, bail");
+            //Log.v("CDMA", "##### processNextPostDialChar: postDialState == CANCELLED, bail");
             return;
         }
 
@@ -646,7 +594,7 @@
                 // Will call processNextPostDialChar
                 h.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
                 // Don't notify application
-                Log.e("GSM", "processNextPostDialChar: c=" + c + " isn't valid!");
+                Log.e("CDMA", "processNextPostDialChar: c=" + c + " isn't valid!");
                 return;
             }
         }
@@ -655,7 +603,8 @@
 
         Message notifyMessage;
 
-        if (postDialHandler != null && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
+        if (postDialHandler != null &&
+                (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
             // The AsyncResult.result is the Connection object
             PostDialState state = postDialState;
             AsyncResult ar = AsyncResult.forMessage(notifyMessage);
@@ -665,17 +614,8 @@
             // arg1 is the character that was/is being processed
             notifyMessage.arg1 = c;
 
-            //Log.v("GSM", "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
             notifyMessage.sendToTarget();
         }
-        /*
-        else {
-            if (postDialHandler == null)
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler is NULL!");
-            else
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler.messageForRegistrant() returned NULL!");
-        }
-        */
     }
 
 
@@ -683,16 +623,14 @@
      *  and outgoing calls
      */
     private boolean
-    isConnectingInOrOut()
-    {
-        return parent == null || parent == owner.ringingCall 
-            || parent.state == Call.State.DIALING 
-            || parent.state == Call.State.ALERTING;
+    isConnectingInOrOut() {
+        return parent == null || parent == owner.ringingCall
+            || parent.state == CdmaCall.State.DIALING
+            || parent.state == CdmaCall.State.ALERTING;
     }
 
-    private GSMCall
-    parentFromDCState (DriverCall.State state)
-    {
+    private CdmaCall
+    parentFromDCState (DriverCall.State state) {
         switch (state) {
             case ACTIVE:
             case DIALING:
@@ -757,7 +695,7 @@
     }
     
     private void log(String msg) {
-        Log.d(LOG_TAG, "[GSMConn] " + msg);
+        Log.d(LOG_TAG, "[CDMAConn] " + msg);
     }
 
     @Override
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
new file mode 100644
index 0000000..2cbad78
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.os.*;
+import android.util.EventLog;
+import android.util.Log;
+
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataLink;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyEventLog;
+
+/**
+ * {@hide}
+ *
+ */
+public class CdmaDataConnection extends DataConnection {
+
+    private static final String LOG_TAG = "CDMA";
+    private static final boolean DBG = true;
+
+    /** Fail cause of last Data Call activate from RIL_LastDataCallActivateFailCause */
+    private final static int PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING         = 8;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_APN                         = 27;
+    private final static int PS_NET_DOWN_REASON_AUTH_FAILED                         = 29;
+    private final static int PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED                = 32;
+    private final static int PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED                 = 33;
+
+/** It is likely that the number of error codes listed below will be removed
+ * in the foreseeable future.  They have been added, but not agreed upon.
+ *
+ */
+    private final static int PS_NET_DOWN_REASON_NOT_SPECIFIED                       = 0;
+    private final static int PS_NET_DOWN_REASON_CLOSE_IN_PROGRESS                   = 1;
+    private final static int PS_NET_DOWN_REASON_NW_INITIATED_TERMINATION            = 2;
+    private final static int PS_NET_DOWN_REASON_APP_PREEMPTED                       = 3;
+    private final static int PS_NET_DOWN_REASON_LLC_SNDCP_FAILURE                   = 25;
+    private final static int PS_NET_DOWN_REASON_INSUFFICIENT_RESOURCES              = 26;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP                         = 28;
+    private final static int PS_NET_DOWN_REASON_GGSN_REJECT                         = 30;
+    private final static int PS_NET_DOWN_REASON_ACTIVATION_REJECT                   = 31;
+    private final static int PS_NET_DOWN_REASON_OPTION_TEMP_OOO                     = 34;
+    private final static int PS_NET_DOWN_REASON_NSAPI_ALREADY_USED                  = 35;
+    private final static int PS_NET_DOWN_REASON_REGULAR_DEACTIVATION                = 36;
+    private final static int PS_NET_DOWN_REASON_QOS_NOT_ACCEPTED                    = 37;
+    private final static int PS_NET_DOWN_REASON_NETWORK_FAILURE                     = 38;
+    private final static int PS_NET_DOWN_REASON_UMTS_REATTACH_REQ                   = 39;
+    private final static int PS_NET_DOWN_REASON_TFT_SEMANTIC_ERROR                  = 41;
+    private final static int PS_NET_DOWN_REASON_TFT_SYNTAX_ERROR                    = 42;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP_CONTEXT                 = 43;
+    private final static int PS_NET_DOWN_REASON_FILTER_SEMANTIC_ERROR               = 44;
+    private final static int PS_NET_DOWN_REASON_FILTER_SYNTAX_ERROR                 = 45;
+    private final static int PS_NET_DOWN_REASON_PDP_WITHOUT_ACTIVE_TFT              = 46;
+    private final static int PS_NET_DOWN_REASON_INVALID_TRANSACTION_ID              = 81;
+    private final static int PS_NET_DOWN_REASON_MESSAGE_INCORRECT_SEMANTIC          = 95;
+    private final static int PS_NET_DOWN_REASON_INVALID_MANDATORY_INFO              = 96;
+    private final static int PS_NET_DOWN_REASON_MESSAGE_TYPE_UNSUPPORTED            = 97;
+    private final static int PS_NET_DOWN_REASON_MSG_TYPE_NONCOMPATIBLE_STATE        = 98;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_INFO_ELEMENT                = 99;
+    private final static int PS_NET_DOWN_REASON_CONDITIONAL_IE_ERROR                = 100;
+    private final static int PS_NET_DOWN_REASON_MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101;
+    private final static int PS_NET_DOWN_REASON_PROTOCOL_ERROR                      = 111;
+    private final static int PS_NET_DOWN_REASON_APN_TYPE_CONFLICT                   = 112;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_CAUSE_CODE                  = 113;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_MIN                        = 200;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_ERROR                      = 201;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_CALL_ENDED                 = 202;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_UNKNOWN_CAUSE_CODE         = 203;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_MAX                        = 204;
+    private final static int PS_NET_DOWN_REASON_CDMA_LOCK                           = 500;
+    private final static int PS_NET_DOWN_REASON_INTERCEPT                           = 501;
+    private final static int PS_NET_DOWN_REASON_REORDER                             = 502;
+    private final static int PS_NET_DOWN_REASON_REL_SO_REJ                          = 503;
+    private final static int PS_NET_DOWN_REASON_INCOM_CALL                          = 504;
+    private final static int PS_NET_DOWN_REASON_ALERT_STOP                          = 505;
+    private final static int PS_NET_DOWN_REASON_ACTIVATION                          = 506;
+    private final static int PS_NET_DOWN_REASON_MAX_ACCESS_PROBE                    = 507;
+    private final static int PS_NET_DOWN_REASON_CCS_NOT_SUPPORTED_BY_BS             = 508;
+    private final static int PS_NET_DOWN_REASON_NO_RESPONSE_FROM_BS                 = 509;
+    private final static int PS_NET_DOWN_REASON_REJECTED_BY_BS                      = 510;
+    private final static int PS_NET_DOWN_REASON_INCOMPATIBLE                        = 511;
+    private final static int PS_NET_DOWN_REASON_ALREADY_IN_TC                       = 512;
+    private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_GPS           = 513;
+    private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_SMS           = 514;
+    private final static int PS_NET_DOWN_REASON_NO_CDMA_SRV                         = 515;
+    private final static int PS_NET_DOWN_REASON_CONF_FAILED                         = 1000;
+    private final static int PS_NET_DOWN_REASON_INCOM_REJ                           = 1001;
+    private final static int PS_NET_DOWN_REASON_NO_GW_SRV                           = 1002;
+    private final static int PS_NET_DOWN_REASON_CD_GEN_OR_BUSY                      = 1500;
+    private final static int PS_NET_DOWN_REASON_CD_BILL_OR_AUTH                     = 1501;
+    private final static int PS_NET_DOWN_REASON_CHG_HDR                             = 1502;
+    private final static int PS_NET_DOWN_REASON_EXIT_HDR                            = 1503;
+    private final static int PS_NET_DOWN_REASON_HDR_NO_SESSION                      = 1504;
+    private final static int PS_NET_DOWN_REASON_HDR_ORIG_DURING_GPS_FIX             = 1505;
+    private final static int PS_NET_DOWN_REASON_HDR_CS_TIMEOUT                      = 1506;
+    private final static int PS_NET_DOWN_REASON_HDR_RELEASED_BY_CM                  = 1507;
+    private final static int PS_NET_DOWN_REASON_CLIENT_END                          = 2000;
+    private final static int PS_NET_DOWN_REASON_NO_SRV                              = 2001;
+    private final static int PS_NET_DOWN_REASON_FADE                                = 2002;
+    private final static int PS_NET_DOWN_REASON_REL_NORMAL                          = 2003;
+    private final static int PS_NET_DOWN_REASON_ACC_IN_PROG                         = 2004;
+    private final static int PS_NET_DOWN_REASON_ACC_FAIL                            = 2005;
+    private final static int PS_NET_DOWN_REASON_REDIR_OR_HANDOFF                    = 2006;
+
+    // ***** Instance Variables
+
+    // ***** Constructor
+    CdmaDataConnection(CDMAPhone phone) {
+        super(phone);
+
+        if (DBG) log("CdmaDataConnection <constructor>");
+    }
+
+    /**
+     * Setup a data connection
+     *
+     * @param onCompleted
+     *            notify success or not after down
+     */
+    void connect(Message onCompleted) {
+        if (DBG) log("CdmaDataConnection Connecting...");
+
+        state = State.ACTIVATING;
+        onConnectCompleted = onCompleted;
+        createTime = -1;
+        lastFailTime = -1;
+        lastFailCause = FailCause.NONE;
+        receivedDisconnectReq = false;
+        phone.mCM.setupDataCall(Integer.toString(RILConstants.CDMA_PHONE), null, null, null,
+                null, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
+    }
+
+    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));
+            }
+        } else if (state == State.ACTIVATING) {
+            receivedDisconnectReq = true;
+        } else {
+            // state == INACTIVE.  Nothing to do, so notify immediately.
+            notifyDisconnect(msg);
+        }
+    }
+
+
+    public String toString() {
+        return "State=" + state + " create=" + createTime + " lastFail="
+                + lastFailTime + " lastFailCause=" + lastFailCause;
+    }
+
+
+    protected void notifyFail(FailCause cause, Message onCompleted) {
+        if (onCompleted == null) {
+            return;
+        }
+        state = State.INACTIVE;
+        lastFailCause = cause;
+        lastFailTime = System.currentTimeMillis();
+        onConnectCompleted = null;
+
+        if(DBG) {
+            log("Notify data connection fail at " + lastFailTime +
+                    " due to " + lastFailCause);
+        }
+
+        AsyncResult.forMessage(onCompleted, cause, new Exception());
+        onCompleted.sendToTarget();
+    }
+
+    protected void notifySuccess(Message onCompleted) {
+        if (onCompleted == null) {
+            return;
+        }
+
+        state = State.ACTIVE;
+        createTime = System.currentTimeMillis();
+        onConnectCompleted = null;
+        onCompleted.arg1 = cid;
+
+        if (DBG) log("Notify data connection success at " + createTime);
+
+        AsyncResult.forMessage(onCompleted);
+        onCompleted.sendToTarget();
+    }
+
+    protected void notifyDisconnect(Message msg) {
+        if (DBG) log("Notify data connection disconnect");
+
+        if (msg != null) {
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+        }
+        clearSettings();
+    }
+
+    protected void onLinkStateChanged(DataLink.LinkState linkState) {
+        switch (linkState) {
+            case LINK_UP:
+                notifySuccess(onConnectCompleted);
+                break;
+
+            case LINK_DOWN:
+            case LINK_EXITED:
+                phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                break;
+        }
+    }
+
+    protected FailCause getFailCauseFromRequest(int rilCause) {
+        FailCause cause;
+
+        switch (rilCause) {
+            case PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING:
+                cause = FailCause.BARRED;
+                break;
+            case PS_NET_DOWN_REASON_AUTH_FAILED:
+                cause = FailCause.USER_AUTHENTICATION;
+                break;
+            case PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED:
+                cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
+                break;
+            case PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED:
+                cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
+                break;
+            default:
+                cause = FailCause.UNKNOWN;
+        }
+        return cause;
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[CdmaDataConnection] " + s);
+    }
+
+    @Override
+    protected void onDeactivated(AsyncResult ar) {
+        notifyDisconnect((Message) ar.userObj);
+        if (DBG) log("CDMA Connection Deactivated");
+    }
+
+    @Override
+    protected void onSetupConnectionCompleted(AsyncResult ar) {
+        if (ar.exception != null) {
+            Log.e(LOG_TAG, "CdmaDataConnection Init failed " + ar.exception);
+
+            if (receivedDisconnectReq) {
+                // Don't bother reporting the error if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                notifyDisconnect(onDisconnect);
+            } else {
+                if (ar.exception instanceof CommandException
+                        && ((CommandException) (ar.exception)).getCommandError()
+                        == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                    notifyFail(FailCause.RADIO_NOT_AVAILABLE, onConnectCompleted);
+                } else {
+                    phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                }
+            }
+        } else {
+            if (receivedDisconnectReq) {
+                // Don't bother reporting success if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                disconnect(onDisconnect);
+            } else {
+                String[] response = ((String[]) ar.result);
+                cid = Integer.parseInt(response[0]);
+
+                if (response.length > 2) {
+                    interfaceName = response[1];
+                    ipAddress = response[2];
+                    String prefix = "net." + interfaceName + ".";
+                    gatewayAddress = SystemProperties.get(prefix + "gw");
+                    dnsServers[0] = SystemProperties.get(prefix + "dns1");
+                    dnsServers[1] = SystemProperties.get(prefix + "dns2");
+                    if (DBG) {
+                        log("interface=" + interfaceName + " ipAddress=" + ipAddress
+                            + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0]
+                            + " DNS2=" + dnsServers[1]);
+                    }
+
+                    if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])
+                                        && !((CDMAPhone) phone).isDnsCheckDisabled()) {
+                        // Work around a race condition where QMI does not fill in DNS:
+                        // Deactivate PDP and let DataConnectionTracker retry.
+                        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
+                                    dnsServers[0]);
+                        phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_FORCE_RETRY));
+                        return;
+                    }
+                }
+
+                onLinkStateChanged(DataLink.LinkState.LINK_UP);
+
+                if (DBG) log("CdmaDataConnection setup on cid = " + cid);
+            }
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
new file mode 100644
index 0000000..651c5051
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -0,0 +1,932 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.INetStatService;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.preference.PreferenceManager;
+import android.provider.Checkin;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.util.EventLog;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.TelephonyEventLog;
+
+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 {
+    private static final String LOG_TAG = "CDMA";
+    private static final boolean DBG = true;
+
+    private CDMAPhone mCdmaPhone;
+
+    // Indicates baseband will not auto-attach
+    private boolean noAutoAttach = false;
+    long nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+    private boolean mIsScreenOn = true;
+
+    //useful for debugging
+    boolean failNextConnect = false;
+
+    /**
+     * dataConnectionList holds all the Data connection
+     */
+    private ArrayList<DataConnection> dataConnectionList;
+
+    /** Currently active CdmaDataConnection */
+    private CdmaDataConnection mActiveDataConnection;
+
+    /** Defined cdma connection profiles */
+    private static final int EXTERNAL_NETWORK_DEFAULT_ID = 0;
+    private static final int EXTERNAL_NETWORK_NUM_TYPES  = 1;
+
+    private boolean[] dataEnabled = new boolean[EXTERNAL_NETWORK_NUM_TYPES];
+
+    /**
+     * Pool size of CdmaDataConnection objects.
+     */
+    private static final int DATA_CONNECTION_POOL_SIZE = 1;
+
+    private static final int POLL_CONNECTION_MILLIS = 5 * 1000;
+    private static final String INTENT_RECONNECT_ALARM =
+            "com.android.internal.telephony.cdma-reconnect";
+    private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+
+    // Possibly promoate to base class, the only difference is
+    // the INTENT_RECONNECT_ALARM action is a different string.
+    // Do consider technology changes if it is promoted.
+    BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
+    {
+        @Override
+        public void onReceive(Context context, Intent intent)
+        {
+            String action = intent.getAction();
+            if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                mIsScreenOn = true;
+                stopNetStatPoll();
+                startNetStatPoll();
+            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                mIsScreenOn = false;
+                stopNetStatPoll();
+                startNetStatPoll();
+            } else if (action.equals((INTENT_RECONNECT_ALARM))) {
+                Log.d(LOG_TAG, "Data reconnect alarm. Previous state was " + state);
+
+                String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+                if (state == State.FAILED) {
+                    cleanUpConnection(false, reason);
+                }
+                trySetupData(reason);
+            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                final android.net.NetworkInfo networkInfo = (NetworkInfo)
+                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+                mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
+            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+
+                if (!enabled) {
+                    // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION
+                    // quit and wont report disconnected til next enalbing.
+                    mIsWifiConnected = false;
+                }
+            }
+        }
+    };
+
+
+    //***** Constructor
+
+    CdmaDataConnectionTracker(CDMAPhone p) {
+        super(p);
+        mCdmaPhone = p;
+
+        p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
+        p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        p.mRuimRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+        p.mCM.registerForNVReady(this, EVENT_NV_READY, null);
+        p.mCM.registerForDataStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
+        p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
+        p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
+        p.mSST.registerForCdmaDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
+        p.mSST.registerForCdmaDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
+        p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
+        p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+
+        this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_RECONNECT_ALARM);
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+
+        p.getContext().registerReceiver(mIntentReceiver, filter, null, p.h);
+
+        mDataConnectionTracker = this;
+
+        createAllDataConnectionList();
+
+        // This preference tells us 1) initial condition for "dataEnabled",
+        // and 2) whether the RIL will setup the baseband to auto-PS attach.
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
+
+        dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID] =
+                !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false);
+        noAutoAttach = !dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
+    }
+
+    public void dispose() {
+        //Unregister from all events
+        phone.mCM.unregisterForAvailable(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this);
+        phone.mCM.unregisterForNVReady(this);
+        phone.mCM.unregisterForDataStateChanged(this);
+        mCdmaPhone.mCT.unregisterForVoiceCallEnded(this);
+        mCdmaPhone.mCT.unregisterForVoiceCallStarted(this);
+        mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this);
+        mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this);
+        mCdmaPhone.mSST.unregisterForRoamingOn(this);
+        mCdmaPhone.mSST.unregisterForRoamingOff(this);
+
+        phone.getContext().unregisterReceiver(this.mIntentReceiver);
+        destroyAllDataConnectionList();
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "CdmaDataConnectionTracker finalized");
+    }
+
+    void setState(State s) {
+        if (DBG) log ("setState: " + s);
+        if (state != s) {
+            if (s == State.INITING) { // request Data connection context
+                Checkin.updateStats(phone.getContext().getContentResolver(),
+                        Checkin.Stats.Tag.PHONE_CDMA_DATA_ATTEMPTED, 1, 0.0);
+            }
+
+            if (s == State.CONNECTED) { // pppd is up
+                Checkin.updateStats(phone.getContext().getContentResolver(),
+                        Checkin.Stats.Tag.PHONE_CDMA_DATA_CONNECTED, 1, 0.0);
+            }
+        }
+
+        state = s;
+    }
+
+    public int enableApnType(String type) {
+        // This request is mainly used to enable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to enableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_ALREADY_ACTIVE;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
+            Log.w(LOG_TAG, "Phone.APN_TYPE_SUPL not enabled for CDMA");
+            return Phone.APN_REQUEST_FAILED;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    public int disableApnType(String type) {
+        // This request is mainly used to disable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to disableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_REQUEST_STARTED;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    private boolean isEnabled(int cdmaDataProfile) {
+        return dataEnabled[cdmaDataProfile];
+    }
+
+    private void setEnabled(int cdmaDataProfile, boolean enable) {
+        Log.d(LOG_TAG, "setEnabled("  + cdmaDataProfile + ", " + enable + ')');
+        dataEnabled[cdmaDataProfile] = enable;
+        Log.d(LOG_TAG, "dataEnabled[DEFAULT_PROFILE]=" + dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID]);
+    }
+
+    /**
+     * Simply tear down data connections due to radio off 
+     * and don't setup again.
+     */
+    public void cleanConnectionBeforeRadioOff() {
+        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+    }
+
+    /**
+     * The data connection is expected to be setup while device
+     *  1. has ruim card or non-volatile data store
+     *  2. registered to data connection service
+     *  3. user doesn't explicitly disable data service
+     *  4. wifi is not on
+     *
+     * @return false while no data connection if all above requirements are met.
+     */
+    public boolean isDataConnectionAsDesired() {
+        boolean roaming = phone.getServiceState().getRoaming();
+
+        if (((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
+                 mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
+                (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
+                 ServiceState.STATE_IN_SERVICE) &&
+                (!roaming || getDataOnRoamingEnabled()) &&
+                !mIsWifiConnected ) {
+            return (state == State.CONNECTED);
+        }
+        return true;
+    }
+
+    /**
+     * Prevent mobile data connections from being established,
+     * or once again allow mobile data connections. If the state
+     * toggles, then either tear down or set up data, as
+     * appropriate to match the new state.
+     * <p>This operation only affects the default connection
+     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+     * @return {@code true} if the operation succeeded
+     */
+    public boolean setDataEnabled(boolean enable) {
+
+        boolean isEnabled = isEnabled(EXTERNAL_NETWORK_DEFAULT_ID);
+
+        Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
+        if (!isEnabled && enable) {
+            setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, true);
+            return trySetupData(Phone.REASON_DATA_ENABLED);
+        } else if (!enable) {
+            setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, false);
+            cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+            return true;
+        } else // isEnabled && enable
+
+        return true;
+    }
+
+    /**
+     * Report the current state of data connectivity (enabled or disabled)
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public boolean getDataEnabled() {
+        return dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
+    }
+
+    /**
+     * Report on whether data connectivity is enabled
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public boolean getAnyDataEnabled() {
+        for (int i=0; i < EXTERNAL_NETWORK_NUM_TYPES; i++) {
+            if (isEnabled(i)) return true;
+        }
+        return false;
+    }
+
+    private boolean isDataAllowed() {
+        boolean roaming = phone.getServiceState().getRoaming();
+        return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled());
+    }
+
+    private boolean trySetupData(String reason) {
+        if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
+
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            setState(State.CONNECTED);
+            phone.notifyDataConnection(reason);
+
+            Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected");
+            return true;
+        }
+
+        int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
+        boolean roaming = phone.getServiceState().getRoaming();
+
+        if ((state == State.IDLE || state == State.SCANNING)
+                && (psState == ServiceState.RADIO_TECHNOLOGY_1xRTT ||
+                    psState == ServiceState.RADIO_TECHNOLOGY_EVDO_0 ||
+                    psState == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
+                && ((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
+                        mCdmaPhone.mRuimRecords.getRecordsLoaded())
+                && (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+                        phone.getState() == Phone.State.IDLE )
+                && isDataAllowed()) {
+
+            return setupData(reason);
+
+        } else {
+            if (DBG) {
+                    log("trySetupData: Not ready for data: " +
+                    " dataState=" + state +
+                    " PS state=" + psState +
+                    " radio state=" + phone.mCM.getRadioState() +
+                    " ruim=" + mCdmaPhone.mRuimRecords.getRecordsLoaded() +
+                    " concurrentVoice&Data=" + mCdmaPhone.mSST.isConcurrentVoiceAndData() +
+                    " phoneState=" + phone.getState() +
+                    " dataEnabled=" + getAnyDataEnabled() +
+                    " roaming=" + roaming +
+                    " dataOnRoamingEnable=" + getDataOnRoamingEnabled());
+            }
+            return false;
+        }
+    }
+
+    /**
+     * If tearDown is true, this only tears down a CONNECTED session. Presently,
+     * there is no mechanism for abandoning an INITING/CONNECTING session,
+     * but would likely involve cancelling pending async requests or
+     * setting a flag or new state to ignore them when they came in
+     * @param tearDown true if the underlying DataConnection should be
+     * disconnected.
+     * @param reason reason for the clean up.
+     */
+    private void cleanUpConnection(boolean tearDown, String reason) {
+        if (DBG) log("Clean up connection due to " + reason);
+
+        // Clear the reconnect alarm, if set.
+        if (mReconnectIntent != null) {
+            AlarmManager am =
+                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+            am.cancel(mReconnectIntent);
+            mReconnectIntent = null;
+        }
+
+        for (DataConnection connBase : dataConnectionList) {
+            CdmaDataConnection conn = (CdmaDataConnection) connBase;
+
+            if(conn != null) {
+                if (tearDown) {
+                    Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
+                    conn.disconnect(msg);
+                } else {
+                    conn.clearSettings();
+                }
+            }
+        }
+
+        stopNetStatPoll();
+
+        /*
+         * If we've been asked to tear down the connection,
+         * set the state to DISCONNECTING. However, there's
+         * a race that can occur if for some reason we were
+         * already in the IDLE state. In that case, the call
+         * to conn.disconnect() above will immediately post
+         * a message to the handler thread that the disconnect
+         * is done, and if the handler runs before the code
+         * below does, the handler will have set the state to
+         * IDLE before the code below runs. If we didn't check
+         * for that, future calls to trySetupData would fail,
+         * and we would never get out of the DISCONNECTING state.
+         */
+        if (!tearDown) {
+            setState(State.IDLE);
+            phone.notifyDataConnection(reason);
+        } else if (state != State.IDLE) {
+            setState(State.DISCONNECTING);
+        }
+    }
+
+    private CdmaDataConnection findFreeDataConnection() {
+        for (DataConnection connBase : dataConnectionList) {
+            CdmaDataConnection conn = (CdmaDataConnection) connBase;
+            if (conn.getState() == DataConnection.State.INACTIVE) {
+                return conn;
+            }
+        }
+        return null;
+    }
+
+    private boolean setupData(String reason) {
+
+        CdmaDataConnection conn = findFreeDataConnection();
+
+        if (conn == null) {
+            if (DBG) log("setupData: No free CdmaDataConnectionfound!");
+            return false;
+        }
+
+        mActiveDataConnection = conn;
+
+        Message msg = obtainMessage();
+        msg.what = EVENT_DATA_SETUP_COMPLETE;
+        msg.obj = reason;
+        conn.connect(msg);
+
+        setState(State.INITING);
+        phone.notifyDataConnection(reason);
+        return true;
+    }
+
+    private void notifyDefaultData(String reason) {
+        setState(State.CONNECTED);
+        phone.notifyDataConnection(reason);
+        startNetStatPoll();
+        // reset reconnect timer
+        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+    }
+
+    private void resetPollStats() {
+        txPkts = -1;
+        rxPkts = -1;
+        sentSinceLastRecv = 0;
+        netStatPollPeriod = POLL_NETSTAT_MILLIS;
+        mNoRecvPollCount = 0;
+    }
+
+    protected void startNetStatPoll() {
+        if (state == State.CONNECTED && netStatPollEnabled == false) {
+            Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
+            resetPollStats();
+            netStatPollEnabled = true;
+            mPollNetStat.run();
+        }
+    }
+
+    protected void stopNetStatPoll() {
+        netStatPollEnabled = false;
+        removeCallbacks(mPollNetStat);
+        Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
+    }
+
+    protected void restartRadio() {
+        Log.d(LOG_TAG, "************TURN OFF RADIO**************");
+        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+        phone.mCM.setRadioPower(false, null);
+        /* Note: no need to call setRadioPower(true).  Assuming the desired
+         * radio power state is still ON (as tracked by ServiceStateTracker),
+         * ServiceStateTracker will call setRadioPower when it receives the
+         * RADIO_STATE_CHANGED notification for the power off.  And if the
+         * desired power state has changed in the interim, we don't want to
+         * override it with an unconditional power on.
+         */
+    }
+    
+    private Runnable mPollNetStat = new Runnable() {
+
+        public void run() {
+            long sent, received;
+            long preTxPkts = -1, preRxPkts = -1;
+
+            Activity newActivity;
+
+            preTxPkts = txPkts;
+            preRxPkts = rxPkts;
+
+            // check if netstat is still valid to avoid NullPointerException after NTC
+            if (netstat != null) {
+                try {
+                    txPkts = netstat.getMobileTxPackets();
+                    rxPkts = netstat.getMobileRxPackets();
+                } catch (RemoteException e) {
+                    txPkts = 0;
+                    rxPkts = 0;
+                }
+
+                //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+
+                if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
+                    sent = txPkts - preTxPkts;
+                    received = rxPkts - preRxPkts;
+
+                    if ( sent > 0 && received > 0 ) {
+                        sentSinceLastRecv = 0;
+                        newActivity = Activity.DATAINANDOUT;
+                    } else if (sent > 0 && received == 0) {
+                        if (phone.getState()  == Phone.State.IDLE) {
+                            sentSinceLastRecv += sent;
+                        } else {
+                            sentSinceLastRecv = 0;
+                        }
+                        newActivity = Activity.DATAOUT;
+                    } else if (sent == 0 && received > 0) {
+                        sentSinceLastRecv = 0;
+                        newActivity = Activity.DATAIN;
+                    } else if (sent == 0 && received == 0) {
+                        newActivity = Activity.NONE;
+                    } else {
+                        sentSinceLastRecv = 0;
+                        newActivity = Activity.NONE;
+                    }
+
+                    if (activity != newActivity) {
+                        activity = newActivity;
+                        phone.notifyDataActivity();
+                    }
+                }
+
+                if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
+                    // we already have NUMBER_SENT_PACKETS sent without ack
+                    if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) {
+                        mNoRecvPollCount++;
+                        // Slow down the poll interval to let things happen
+                        netStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
+                    } else {
+                        if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
+                                            " pkts since last received");
+                        // We've exceeded the threshold.  Restart the radio.
+                        netStatPollEnabled = false;
+                        stopNetStatPoll();
+                        restartRadio();
+                    }
+                } else {
+                    mNoRecvPollCount = 0;
+                    netStatPollPeriod = POLL_NETSTAT_MILLIS;
+                }
+
+                if (netStatPollEnabled) {
+                    mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
+                }
+            }
+        }
+    };
+
+    /**
+     * Returns true if the last fail cause is something that
+     * seems like it deserves an error notification.
+     * Transient errors are ignored
+     */
+    private boolean
+    shouldPostNotification(FailCause cause) {
+        return (cause != FailCause.UNKNOWN);
+    }
+
+    /**
+     * Return true if data connection need to be setup after disconnected due to
+     * reason.
+     * 
+     * @param reason the reason why data is disconnected
+     * @return true if try setup data connection is need for this reason 
+     */
+    private boolean retryAfterDisconnected(String reason) {
+        boolean retry = true;
+        
+        if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
+             Phone.REASON_DATA_DISABLED.equals(reason) ) { 
+            retry = false;
+        }
+        return retry;
+    }   
+
+    private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
+        if (state == State.FAILED) {
+            Log.d(LOG_TAG, "Data Connection activate failed. Scheduling next attempt for "
+                    + (nextReconnectDelay / 1000) + "s");
+
+            AlarmManager am =
+                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+            Intent intent = new Intent(INTENT_RECONNECT_ALARM);
+            intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
+            mReconnectIntent = PendingIntent.getBroadcast(
+                    phone.getContext(), 0, intent, 0);
+            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    SystemClock.elapsedRealtime() + nextReconnectDelay,
+                    mReconnectIntent);
+
+            // double it for next time
+            nextReconnectDelay *= 2;
+            if (nextReconnectDelay > RECONNECT_DELAY_MAX_MILLIS) {
+                nextReconnectDelay = RECONNECT_DELAY_MAX_MILLIS;
+            }
+
+            if (!shouldPostNotification(lastFailCauseCode)) {
+                Log.d(LOG_TAG,"NOT Posting Data Connection Unavailable notification "
+                                + "-- likely transient error");
+            } else {
+                notifyNoData(lastFailCauseCode);
+            }
+        }
+    }
+
+    private void notifyNoData(FailCause lastFailCauseCode) {
+        setState(State.FAILED);
+    }
+
+    protected void onRecordsLoaded() {
+        if (state == State.FAILED) {
+            cleanUpConnection(false, null);
+        }
+        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+    }
+
+    protected void onNVReady() {
+        if (state == State.FAILED) {
+            cleanUpConnection(false, null);
+        }
+        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onTrySetupData() {
+        trySetupData(null);
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRoamingOff() {
+        trySetupData(Phone.REASON_ROAMING_OFF);
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRoamingOn() {
+        if (getDataOnRoamingEnabled()) {
+            trySetupData(Phone.REASON_ROAMING_ON);
+        } else {
+            if (DBG) log("Tear down data connection on roaming.");
+            cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRadioAvailable() {
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            setState(State.CONNECTED);
+            phone.notifyDataConnection(null);
+
+            Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+        }
+
+        if (state != State.IDLE) {
+            cleanUpConnection(true, null);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRadioOffOrNotAvailable() {
+        // Make sure our reconnect delay starts at the initial value
+        // next time the radio comes on
+        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+        } else {
+            if (DBG) log("Radio is off and clean up all connection");
+            cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onDataSetupComplete(AsyncResult ar) {
+        String reason = null;
+        if (ar.userObj instanceof String) {
+            reason = (String) ar.userObj;
+        }
+
+        if (ar.exception == null) {
+            // everything is setup
+            notifyDefaultData(reason);
+        } else {
+            FailCause cause = (FailCause) (ar.result);
+            if(DBG) log("Data Connection setup failed " + cause);
+
+            // No try for permanent failure
+            if (cause.isPermanentFail()) {
+                notifyNoData(cause);
+            }
+
+            if (tryAgain(cause)) {
+                    trySetupData(reason);
+            } else {
+                startDelayedRetry(cause, reason);
+            }
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onDisconnectDone(AsyncResult ar) {
+        if(DBG) log("EVENT_DISCONNECT_DONE");
+        String reason = null;
+        if (ar.userObj instanceof String) {
+            reason = (String) ar.userObj;
+        }
+        setState(State.IDLE);
+        phone.notifyDataConnection(reason);
+        if (retryAfterDisconnected(reason)) {
+          trySetupData(reason);
+      }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onVoiceCallStarted() {
+        if (state == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+            stopNetStatPoll();
+            phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onVoiceCallEnded() {
+        if (state == State.CONNECTED) {
+            if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+                startNetStatPoll();
+                phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
+            } else {
+                // clean slate after call end.
+                resetPollStats();
+            }
+        } else {
+            // in case data setup was attempted when we were on a voice call
+            trySetupData(Phone.REASON_VOICE_CALL_ENDED);
+        }
+    }
+
+    private boolean tryAgain(FailCause cause) {
+        return (cause != FailCause.RADIO_NOT_AVAILABLE)
+            && (cause != FailCause.RADIO_OFF)
+            && (cause != FailCause.RADIO_ERROR_RETRY)
+            && (cause != FailCause.NO_SIGNAL)
+            && (cause != FailCause.SIM_LOCKED);
+    }
+
+    private void createAllDataConnectionList() {
+       dataConnectionList = new ArrayList<DataConnection>();
+        CdmaDataConnection dataConn;
+
+       for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
+            dataConn = new CdmaDataConnection(mCdmaPhone);
+            dataConnectionList.add(dataConn);
+       }
+    }
+
+    private void destroyAllDataConnectionList() {
+        if(dataConnectionList != null) {
+            dataConnectionList.removeAll(dataConnectionList);
+        }
+    }
+
+    private void onCdmaDataAttached() {
+        if (state == State.CONNECTED) {
+            startNetStatPoll();
+            phone.notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED);
+        } else {
+            if (state == State.FAILED) {
+                cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
+                nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+            }
+            trySetupData(Phone.REASON_CDMA_DATA_DETACHED);
+        }
+    }
+
+    protected void onDataStateChanged (AsyncResult ar) {
+        if (ar.exception != null) {
+            // This is probably "radio not available" or something
+            // of that sort. If so, the whole connection is going
+            // to come down soon anyway
+            return;
+        }
+
+        if (state == State.CONNECTED) {
+            Log.i(LOG_TAG, "Data connection has changed.");
+
+            int cid = -1;
+            EventLog.List val = new EventLog.List(cid,
+                    TelephonyManager.getDefault().getNetworkType());
+            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
+
+            cleanUpConnection(true, null);
+        }
+        Log.i(LOG_TAG, "Data connection has changed.");
+    }
+
+    String getInterfaceName() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getInterface();
+        }
+        return null;
+    }
+
+    protected String getIpAddress() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getIpAddress();
+        }
+        return null;
+    }
+
+    String getGateway() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getGatewayAddress();
+        }
+        return null;
+    }
+
+    protected String[] getDnsServers() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getDnsServers();
+        }
+        return null;
+    }
+
+    public ArrayList<DataConnection> getAllDataConnections() {
+        return dataConnectionList;
+    }
+
+    private void startDelayedRetry(FailCause cause, String reason) {
+        notifyNoData(cause);
+        reconnectAfterFail(cause, reason);
+    }
+
+    public void handleMessage (Message msg) {
+
+        switch (msg.what) {
+            case EVENT_RECORDS_LOADED:
+                onRecordsLoaded();
+                break;
+
+            case EVENT_NV_READY:
+                onNVReady();
+                break;
+
+            case EVENT_CDMA_DATA_DETACHED:
+                onCdmaDataAttached();
+                break;
+
+            case EVENT_DATA_STATE_CHANGED:
+                onDataStateChanged((AsyncResult) msg.obj);
+                break;
+
+            default:
+                // handle the message in the super class DataConnectionTracker
+                super.handleMessage(msg);
+                break;
+        }
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
new file mode 100644
index 0000000..42c0583
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+
+import android.app.PendingIntent;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.util.Config;
+import android.util.Log;
+
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SMSDispatcher;
+//import com.android.internal.telephony.SMSDispatcher.SmsTracker;
+import com.android.internal.telephony.cdma.SmsMessage;
+import com.android.internal.telephony.cdma.sms.SmsEnvelope;
+import com.android.internal.util.HexDump;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+
+final class CdmaSMSDispatcher extends SMSDispatcher {
+    private static final String TAG = "CDMA";
+
+    CdmaSMSDispatcher(CDMAPhone phone) {
+        super(phone);
+    }
+
+    /**
+     * Called when a status report is received.  This should correspond to
+     * a previously successful SEND.
+     * Is a special GSM function, should never be called in CDMA!!
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           be a String representing the status report PDU, as ASCII hex.
+     */
+    protected void handleStatusReport(AsyncResult ar) {
+        Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!");
+    }
+
+    /**
+     * Dispatches an incoming SMS messages.
+     *
+     * @param smsb the incoming message from the phone
+     */
+    protected void dispatchMessage(SmsMessageBase smsb) {
+
+        // If sms is null, means there was a parsing error.
+        // TODO: Should NAK this.
+        if (smsb == null) {
+            return;
+        }
+        SmsMessage sms = (SmsMessage) smsb;
+        int teleService;
+        boolean handled = false;
+
+        // Decode BD stream and set sms variables.
+        sms.parseSms();
+        teleService = sms.getTeleService();
+
+        // Teleservices W(E)MT and VMN are handled together:
+        if ((SmsEnvelope.TELESERVICE_WMT == teleService)
+                ||(SmsEnvelope.TELESERVICE_WEMT == teleService)
+                ||(SmsEnvelope.TELESERVICE_VMN == teleService)){
+            // From here on we need decoded BD.
+            // Special case the message waiting indicator messages
+            if (sms.isMWISetMessage()) {
+                ((CDMAPhone) mPhone).updateMessageWaitingIndicator(true);
+
+                if (sms.isMwiDontStore()) {
+                    handled = true;
+                }
+
+                if (Config.LOGD) {
+                    Log.d(TAG,
+                            "Received voice mail indicator set SMS shouldStore=" + !handled);
+                }
+            } else if (sms.isMWIClearMessage()) {
+                ((CDMAPhone) mPhone).updateMessageWaitingIndicator(false);
+
+                if (sms.isMwiDontStore()) {
+                    handled = true;
+                }
+
+                if (Config.LOGD) {
+                    Log.d(TAG,
+                            "Received voice mail indicator clear SMS shouldStore=" + !handled);
+                }
+            }
+        }
+
+        if (null == sms.getUserData()){
+            handled = true;
+            if (Config.LOGD) {
+                Log.d(TAG, "Received SMS without user data");
+            }
+        }
+
+        if (handled) return;
+
+        if (SmsEnvelope.TELESERVICE_WAP == teleService){
+            processCdmaWapPdu(sms.getUserData(), sms.messageRef, sms.getOriginatingAddress());
+            return;
+        }
+
+        // Parse the headers to see if this is partial, or port addressed
+        int referenceNumber = -1;
+        int count = 0;
+        int sequence = 0;
+        int destPort = -1;
+        // From here on we need BD distributed to SMS member variables.
+
+        SmsHeader header = sms.getUserDataHeader();
+        if (header != null) {
+            for (SmsHeader.Element element : header.getElements()) {
+                try {
+                    switch (element.getID()) {
+                        case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = data[0] & 0xff;
+                            count = data[1] & 0xff;
+                            sequence = data[2] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
+                            count = data[2] & 0xff;
+                            sequence = data[3] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
+                            byte[] data = element.getData();
+                            
+                            destPort = (data[0] & 0xff) << 8;
+                            destPort |= (data[1] & 0xff);
+                            
+                            break;
+                        }
+                    }
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    Log.e(TAG, "Bad element in header", e);
+                    return;  // TODO: NACK the message or something, don't just discard.
+                }
+            }
+        }
+
+        if (referenceNumber == -1) {
+            // notify everyone of the message if it isn't partial
+            byte[][] pdus = new byte[1][];
+            pdus[0] = sms.getPdu();
+
+            if (destPort != -1) {// GSM-style WAP indication
+                if (destPort == SmsHeader.PORT_WAP_PUSH) {
+                    mWapPush.dispatchWapPdu(sms.getUserData());
+                }
+                // The message was sent to a port, so concoct a URI for it
+                dispatchPortAddressedPdus(pdus, destPort);
+            } else {
+                // It's a normal message, dispatch it
+                dispatchPdus(pdus);
+            }
+        } else {
+            // Process the message part
+            processMessagePart(sms, referenceNumber, sequence, count, destPort);
+        }
+    }
+
+    /**
+     * Processes inbound messages that are in the WAP-WDP PDU format. See
+     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
+     * WDP segments are gathered until a datagram completes and gets dispatched.
+     *
+     * @param pdu The WAP-WDP PDU segment
+     */
+    protected void processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) {
+        int segment;
+        int totalSegments;
+        int index = 0;
+        int msgType;
+
+        int sourcePort;
+        int destinationPort;
+
+        msgType = pdu[index++];
+        if (msgType != 0){
+            Log.w(TAG, "Received a WAP SMS which is not WDP. Discard.");
+            return;
+        }
+        totalSegments = pdu[index++]; // >=1
+        segment = pdu[index++]; // >=0
+
+        //process WDP segment
+        sourcePort = (0xFF & pdu[index++]) << 8;
+        sourcePort |= 0xFF & pdu[index++];
+        destinationPort = (0xFF & pdu[index++]) << 8;
+        destinationPort |= 0xFF & pdu[index++];
+
+        // Lookup all other related parts
+        StringBuilder where = new StringBuilder("reference_number =");
+        where.append(referenceNumber);
+        where.append(" AND address = ?");
+        String[] whereArgs = new String[] {address};
+
+        Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address
+                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
+                + ", ID = " + referenceNumber + ", segment# = " + segment + "/" + totalSegments);
+
+        byte[][] pdus = null;
+        Cursor cursor = null;
+        try {
+            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
+            int cursorCount = cursor.getCount();
+            if (cursorCount != totalSegments - 1) {
+                // We don't have all the parts yet, store this one away
+                ContentValues values = new ContentValues();
+                values.put("date", new Long(0));
+                values.put("pdu", HexDump.toHexString(pdu, index, pdu.length - index));
+                values.put("address", address);
+                values.put("reference_number", referenceNumber);
+                values.put("count", totalSegments);
+                values.put("sequence", segment);
+                values.put("destination_port", destinationPort);
+
+                mResolver.insert(mRawUri, values);
+
+                return;
+            }
+
+            // All the parts are in place, deal with them
+            int pduColumn = cursor.getColumnIndex("pdu");
+            int sequenceColumn = cursor.getColumnIndex("sequence");
+
+            pdus = new byte[totalSegments][];
+            for (int i = 0; i < cursorCount; i++) {
+                cursor.moveToNext();
+                int cursorSequence = (int)cursor.getLong(sequenceColumn);
+                pdus[cursorSequence] = HexDump.hexStringToByteArray(
+                        cursor.getString(pduColumn));
+            }
+            // The last part will be added later
+
+            // Remove the parts from the database
+            mResolver.delete(mRawUri, where.toString(), whereArgs);
+        } catch (SQLException e) {
+            Log.e(TAG, "Can't access multipart SMS database", e);
+            return;  // TODO: NACK the message or something, don't just discard.
+        } finally {
+            if (cursor != null) cursor.close();
+        }
+
+        // Build up the data stream
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        for (int i = 0; i < totalSegments-1; i++) {
+            // reassemble the (WSP-)pdu
+            output.write(pdus[i], 0, pdus[i].length);
+        }
+
+        // This one isn't in the DB, so add it
+        output.write(pdu, index, pdu.length - index);
+
+        byte[] datagram = output.toByteArray();
+        // Dispatch the PDU to applications
+        switch (destinationPort) {
+        case SmsHeader.PORT_WAP_PUSH:
+            // Handle the PUSH
+            mWapPush.dispatchWapPdu(datagram);
+            break;
+
+        default:{
+            pdus = new byte[1][];
+            pdus[0] = datagram;
+            // The messages were sent to any other WAP port
+            dispatchPortAddressedPdus(pdus, destinationPort);
+            break;
+        }
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void sendMultipartText(String destinationAddress, String scAddress,
+            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
+            ArrayList<PendingIntent> deliveryIntents) {
+
+        int ref = ++sConcatenatedRef & 0xff;
+
+        for (int i = 0, count = parts.size(); i < count; i++) {
+            // build SmsHeader data
+            byte[] data = new byte[5];
+            data[0] = (byte) SmsHeader.CONCATENATED_8_BIT_REFERENCE;
+            data[1] = (byte) 3;   // 3 bytes follow
+            data[2] = (byte) ref;   // reference #, unique per message
+            data[3] = (byte) count; // total part count
+            data[4] = (byte) (i + 1);  // 1-based sequence
+
+            PendingIntent sentIntent = null;
+            PendingIntent deliveryIntent = null;
+
+            if (sentIntents != null && sentIntents.size() > i) {
+                sentIntent = sentIntents.get(i);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > i) {
+                deliveryIntent = deliveryIntents.get(i);
+            }
+
+            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
+                    parts.get(i), deliveryIntent != null, data);
+
+            sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+        }
+    }
+
+    protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        super.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+    }
+
+    /** {@inheritDoc} */
+    protected void sendSms(SmsTracker tracker) {
+        HashMap map = tracker.mData;
+
+        byte smsc[] = (byte[]) map.get("smsc");
+        byte pdu[] = (byte[]) map.get("pdu");
+
+        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
+
+        mCm.sendCdmaSms(pdu, reply);
+    }
+
+     /** {@inheritDoc} */
+    protected void sendMultipartSms (SmsTracker tracker) {
+        Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented");
+    }
+
+    /** {@inheritDoc} */
+    protected void acknowledgeLastIncomingSms(boolean success, Message response){
+        // FIXME unit test leaves cm == null. this should change
+        if (mCm != null) {
+            mCm.acknowledgeLastIncomingCdmaSms(success, response);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void activateCellBroadcastSms(int activate, Message response) {
+        mCm.activateCdmaBroadcastSms(activate, response);
+    }
+
+    /** {@inheritDoc} */
+    protected void getCellBroadcastSmsConfig(Message response) {
+        mCm.getCdmaBroadcastConfig(response);
+    }
+
+    /** {@inheritDoc} */
+    protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+        mCm.setCdmaBroadcastConfig(configValuesArray, response);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
new file mode 100644
index 0000000..d5cad1c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.app.AlarmManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.Checkin;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.provider.Telephony.Intents;
+import android.telephony.ServiceState;
+import android.telephony.cdma.CdmaCellLocation;
+import android.text.TextUtils;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.TimeUtils;
+
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+// pretty sure importing stuff from GSM is bad:
+import com.android.internal.telephony.gsm.MccTable;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.TelephonyIntents;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISMANUAL;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * {@hide}
+ */
+final class CdmaServiceStateTracker extends ServiceStateTracker {
+    //***** Instance Variables
+    CDMAPhone phone;
+    CdmaCellLocation cellLoc;
+    CdmaCellLocation newCellLoc;
+
+    int rssi = 99;  // signal strength 0-31, 99=unknown
+    // That's "received signal strength indication" fyi
+
+    /**
+     *  The access technology currently in use: DATA_ACCESS_
+     */
+    private int networkType = 0;
+    private int newNetworkType = 0;
+
+    private boolean mCdmaRoaming = false;
+
+    private int cdmaDataConnectionState = -1;//Initial we assume no data connection
+    private int newCdmaDataConnectionState = -1;//Initial we assume no data connection
+    private int mRegistrationState = -1;
+    private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList();
+    private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
+
+    private boolean mGotCountryCode = false;
+
+    // We can't register for SIM_RECORDS_LOADED immediately because the
+    // SIMRecords object may not be instantiated yet.
+    private boolean mNeedToRegForRuimLoaded;
+
+    // Keep track of SPN display rules, so we only broadcast intent if something changes.
+    private String curSpn = null;
+    private String curPlmn = null;
+    private int curSpnRule = 0;
+
+    //***** Constants
+    static final String LOG_TAG = "CDMA";
+    static final String TMUK = "23430";
+
+    private ContentResolver cr;
+
+    private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
+        @Override
+        public void onChange(boolean selfChange) {
+            Log.i("CdmaServiceStateTracker", "Auto time state called ...");
+            //NOTE in CDMA NITZ is not used
+        }
+    };
+
+
+    //***** Constructors
+
+    public CdmaServiceStateTracker(CDMAPhone phone) {
+        super();
+
+        this.phone = phone;
+        cm = phone.mCM;
+        ss = new ServiceState();
+        newSS = new ServiceState();
+        cellLoc = new CdmaCellLocation();
+        newCellLoc = new CdmaCellLocation();
+
+        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
+        cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
+
+        cm.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED_CDMA, null);
+        cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
+
+        cm.registerForRUIMReady(this, EVENT_RUIM_READY, null);
+
+        phone.registerForNvLoaded(this, EVENT_NV_LOADED,null);
+
+        // system setting property AIRPLANE_MODE_ON is set in Settings.
+        int airplaneMode = Settings.System.getInt(
+                phone.getContext().getContentResolver(),
+                Settings.System.AIRPLANE_MODE_ON, 0);
+        mDesiredPowerState = ! (airplaneMode > 0);
+
+        cr = phone.getContext().getContentResolver();
+        cr.registerContentObserver(
+                Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
+                mAutoTimeObserver);
+        setRssiDefaultValues();
+
+        mNeedToRegForRuimLoaded = true;
+    }
+
+    public void dispose() {
+        //Unregister for all events
+        cm.unregisterForAvailable(this);
+        cm.unregisterForRadioStateChanged(this);
+        cm.unregisterForNetworkStateChanged(this);
+        cm.unregisterForRUIMReady(this);
+        phone.unregisterForNvLoaded(this);
+        phone.mRuimRecords.unregisterForRecordsLoaded(this);
+        cm.unSetOnSignalStrengthUpdate(this);
+        cr.unregisterContentObserver(this.mAutoTimeObserver);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "CdmaServiceStateTracker finalized");
+    }
+
+    void registerForNetworkAttach(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        networkAttachedRegistrants.add(r);
+
+        if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+            r.notifyRegistrant();
+        }
+    }
+
+    void unregisterForNetworkAttach(Handler h) {
+        networkAttachedRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition into Data attached.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    /*protected*/ void
+    registerForCdmaDataConnectionAttached(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        cdmaDataConnectionAttachedRegistrants.add(r);
+
+        if (cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_1xRTT
+           || cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_0
+           || cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_A) {
+            r.notifyRegistrant();
+        }
+    }
+    void unregisterForCdmaDataConnectionAttached(Handler h) {
+        cdmaDataConnectionAttachedRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition into Data detached.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    /*protected*/  void
+    registerForCdmaDataConnectionDetached(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        cdmaDataConnectionDetachedRegistrants.add(r);
+
+        if (cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_1xRTT
+           && cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_0
+           && cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_A) {
+            r.notifyRegistrant();
+        }
+    }
+    void unregisterForCdmaDataConnectionDetached(Handler h) {
+        cdmaDataConnectionDetachedRegistrants.remove(h);
+    }
+
+    //***** Called from CDMAPhone
+    public void
+    getLacAndCid(Message onComplete) {
+        cm.getRegistrationState(obtainMessage(
+                EVENT_GET_LOC_DONE_CDMA, onComplete));
+    }
+
+
+    //***** Overridden from ServiceStateTracker
+    public void
+    handleMessage (Message msg) {
+        AsyncResult ar;
+        int[] ints;
+        String[] strings;
+
+        switch (msg.what) {
+        case EVENT_RADIO_AVAILABLE:
+            //this is unnecessary
+            //setPowerStateToDesired();
+            break;
+
+        case EVENT_RUIM_READY:
+            // The RUIM is now ready i.e if it was locked
+            // it has been unlocked. At this stage, the radio is already
+            // powered on.
+            if (mNeedToRegForRuimLoaded) {
+                phone.mRuimRecords.registerForRecordsLoaded(this,
+                        EVENT_RUIM_RECORDS_LOADED, null);
+                mNeedToRegForRuimLoaded = false;
+            }
+            // restore the previous network selection.
+            phone.restoreSavedNetworkSelection(null);
+            pollState();
+            // Signal strength polling stops when radio is off
+            queueNextSignalStrengthPoll();
+            break;
+
+        case EVENT_RADIO_STATE_CHANGED:
+            // This will do nothing in the radio not
+            // available case
+            setPowerStateToDesired();
+            pollState();
+            break;
+
+        case EVENT_NETWORK_STATE_CHANGED_CDMA:
+            pollState();
+            break;
+
+        case EVENT_GET_SIGNAL_STRENGTH:
+            // This callback is called when signal strength is polled
+            // all by itself
+
+            if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isGsm())) {
+                // Polling will continue when radio turns back on
+                return;
+            }
+            ar = (AsyncResult) msg.obj;
+            onSignalStrengthResult(ar);
+            queueNextSignalStrengthPoll();
+
+            break;
+
+        case EVENT_GET_LOC_DONE_CDMA:
+            ar = (AsyncResult) msg.obj;
+
+            if (ar.exception == null) {
+                String states[] = (String[])ar.result;
+                int baseStationId = -1;
+                int baseStationLongitude = -1;
+                int baseStationLatitude = -1;
+
+                int baseStationData[] = {
+                        -1, // baseStationId
+                        -1, // baseStationLatitude
+                        -1  // baseStationLongitude
+                };
+
+                if (states.length == 3) {
+                    for(int i = 0; i < states.length; i++) {
+                        try {
+                            if (states[i] != null && states[i].length() > 0) {
+                                baseStationData[i] = Integer.parseInt(states[i], 16);
+                            }
+                        } catch (NumberFormatException ex) {
+                            Log.w(LOG_TAG, "error parsing cell location data: " + ex);
+                        }
+                    }
+                }
+
+                // only update if cell location really changed
+                if (cellLoc.getBaseStationId() != baseStationData[0]
+                        || cellLoc.getBaseStationLatitude() != baseStationData[1]
+                        || cellLoc.getBaseStationLongitude() != baseStationData[2]) {
+                    cellLoc.setCellLocationData(baseStationData[0],
+                                                baseStationData[1],
+                                                baseStationData[2]);
+                   phone.notifyLocationChanged();
+                }
+            }
+
+            if (ar.userObj != null) {
+                AsyncResult.forMessage(((Message) ar.userObj)).exception
+                = ar.exception;
+                ((Message) ar.userObj).sendToTarget();
+            }
+            break;
+
+        case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA: //Fall through
+        case EVENT_POLL_STATE_REGISTRATION_CDMA: //Fall through
+        case EVENT_POLL_STATE_OPERATOR_CDMA:
+            ar = (AsyncResult) msg.obj;
+            handlePollStateResult(msg.what, ar);
+            break;
+
+        case EVENT_POLL_SIGNAL_STRENGTH:
+            // Just poll signal strength...not part of pollState()
+
+            cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
+            break;
+
+        case EVENT_SIGNAL_STRENGTH_UPDATE:
+            // This is a notification from
+            // CommandsInterface.setOnSignalStrengthUpdate
+
+            ar = (AsyncResult) msg.obj;
+
+            // The radio is telling us about signal strength changes
+            // we don't have to ask it
+            dontPollSignalStrength = true;
+
+            onSignalStrengthResult(ar);
+            break;
+
+        case EVENT_RUIM_RECORDS_LOADED:
+        case EVENT_NV_LOADED:
+            updateSpnDisplay();
+            break;
+
+        case EVENT_LOCATION_UPDATES_ENABLED:
+            ar = (AsyncResult) msg.obj;
+
+            if (ar.exception == null) {
+                getLacAndCid(null);
+            }
+            break;
+
+        default:
+            Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+        break;
+        }
+    }
+
+    //***** Private Instance Methods
+
+    protected void setPowerStateToDesired()
+    {
+        // If we want it on and it's off, turn it on
+        if (mDesiredPowerState
+            && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
+            cm.setRadioPower(true, null);
+        } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
+            DataConnectionTracker dcTracker = phone.mDataConnection;
+            if (! dcTracker.isDataConnectionAsDesired()) {
+
+                EventLog.List val = new EventLog.List(
+                        dcTracker.getStateInString(),
+                        (dcTracker.getAnyDataEnabled() ? 1 : 0) );
+                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
+            }
+            dcTracker.cleanConnectionBeforeRadioOff();
+            
+            // poll data state up to 15 times, with a 100ms delay
+            // totaling 1.5 sec. Normal data disable action will finish in 100ms.
+            for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
+                if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED 
+                        && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
+                    Log.d(LOG_TAG, "Data shutdown complete.");
+                    break;
+                }
+                SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
+            }
+            // If it's on and available and we want it off..
+            cm.setRadioPower(false, null);
+        } // Otherwise, we're in the desired state
+    }
+
+    protected void updateSpnDisplay() {
+
+        // TODO Check this method again, because it is not sure at the moment how
+        // the RUIM handles the SIM stuff
+
+        //int rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric());
+        String spn = null; //phone.mRuimRecords.getServiceProviderName();
+        String plmn = ss.getOperatorAlphaLong();
+
+        if (!TextUtils.equals(this.curPlmn, plmn)) {
+            //TODO  (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
+            boolean showSpn = false;
+            //TODO  (rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
+            boolean showPlmn = true;
+            Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
+            intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
+            intent.putExtra(Intents.EXTRA_SPN, spn);
+            intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
+            intent.putExtra(Intents.EXTRA_PLMN, plmn);
+            phone.getContext().sendStickyBroadcast(intent);
+        }
+
+        //curSpnRule = rule;
+        //curSpn = spn;
+        this.curPlmn = plmn;
+    }
+
+    /**
+     * Handle the result of one of the pollState()-related requests
+     */
+
+    protected void
+    handlePollStateResult (int what, AsyncResult ar) {
+        int ints[];
+        String states[];
+
+        // Ignore stale requests from last poll
+        if (ar.userObj != pollingContext) return;
+
+        if (ar.exception != null) {
+            CommandException.Error err=null;
+
+            if (ar.exception instanceof CommandException) {
+                err = ((CommandException)(ar.exception)).getCommandError();
+            }
+
+            if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                // Radio has crashed or turned off
+                cancelPollState();
+                return;
+            }
+
+            if (!cm.getRadioState().isOn()) {
+                // Radio has crashed or turned off
+                cancelPollState();
+                return;
+            }
+
+            if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
+                    err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
+                Log.e(LOG_TAG,
+                        "RIL implementation has returned an error where it must succeed",
+                        ar.exception);
+            }
+        } else try {
+            switch (what) {
+            case EVENT_POLL_STATE_REGISTRATION_CDMA:
+                //offset, because we don't want the first 3 values in the int-array
+                final int offset = 3;
+                states = (String[])ar.result;
+
+                int responseValuesRegistrationState[] = {
+                        -1, //[0] radioTechnology
+                        -1, //[1] baseStationId
+                        -1, //[2] baseStationLatitude
+                        -1, //[3] baseStationLongitude
+                         0, //[4] cssIndicator; init with 0, because it is treated as a boolean
+                        -1, //[5] systemId
+                        -1, //[6] networkId
+                        -1, //[7] TSB-58 Roaming indicator // NEWRIL:TODO UNUSED
+                        -1, //[8] Indicates if current system is in PRL  // NEWRIL:TODO UNUSED
+                        -1, //[9] Is default roaming indicator from PRL // NEWRIL:TODO UNUSED
+                        -1, //[10] If registration state is 3 this is reason for denial // NEWRIL:TODO UNUSED
+                };
+
+                if (states.length > 0) {
+                    try {
+                        this.mRegistrationState = Integer.parseInt(states[0]);
+                        if (states.length >= 10) {
+                            for(int i = 0; i < states.length - offset; i++) {
+                                if (states[i + offset] != null
+                                  && states[i + offset].length() > 0) {
+                                    try {
+                                        responseValuesRegistrationState[i] =
+                                           Integer.parseInt(states[i + offset], 16);
+                                    }
+                                    catch(NumberFormatException ex) {
+                                        Log.w(LOG_TAG, "Warning! There is an unexpected value"
+                                            + "returned as response from " 
+                                            + "RIL_REQUEST_REGISTRATION_STATE.");
+                                    }
+                                }
+                            }
+                        }
+                        else {
+                            Log.e(LOG_TAG, "Too less parameters returned from"
+                                + " RIL_REQUEST_REGISTRATION_STATE");
+                        }
+                    } catch (NumberFormatException ex) {
+                        Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
+                    }
+                }
+
+                mCdmaRoaming = regCodeIsRoaming(this.mRegistrationState);
+                this.newCdmaDataConnectionState =
+                    radioTechnologyToServiceState(responseValuesRegistrationState[0]);
+                newSS.setState (regCodeToServiceState(this.mRegistrationState));
+                newSS.setRadioTechnology(responseValuesRegistrationState[0]);
+                newSS.setCssIndicator(responseValuesRegistrationState[4]);
+                newSS.setSystemAndNetworkId(responseValuesRegistrationState[5],
+                    responseValuesRegistrationState[6]);
+
+                newNetworkType = responseValuesRegistrationState[0];
+
+                // values are -1 if not available
+                newCellLoc.setCellLocationData(responseValuesRegistrationState[1],
+                                               responseValuesRegistrationState[2],
+                                               responseValuesRegistrationState[3]);
+                break;
+
+            case EVENT_POLL_STATE_OPERATOR_CDMA:
+                String opNames[] = (String[])ar.result;
+
+                if (opNames != null && opNames.length >= 3) {
+                    newSS.setOperatorName (opNames[0], opNames[1], opNames[2]);
+                }
+                break;
+
+            case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA:
+                ints = (int[])ar.result;
+                newSS.setIsManualSelection(ints[0] == 1);
+                break;
+            default:
+                Log.e(LOG_TAG, "RIL response handle in wrong phone!"
+                    + " Expected CDMA RIL request and get GSM RIL request.");
+            break;
+            }
+
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "Exception while polling service state. "
+                    + "Probably malformed RIL response.", ex);
+        }
+
+        pollingContext[0]--;
+
+        if (pollingContext[0] == 0) {
+            newSS.setRoaming(isRoamingBetweenOperators(mCdmaRoaming, newSS));
+
+            switch(this.mRegistrationState) {
+            case ServiceState.REGISTRATION_STATE_HOME_NETWORK:
+                newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_HOME_NETWORK);
+                break;
+            case ServiceState.REGISTRATION_STATE_ROAMING:
+                newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_ROAMING);
+                break;
+            case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
+                newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE);
+                break;
+            default:
+                Log.w(LOG_TAG, "Received a different registration state, "
+                    + "but don't changed the extended cdma roaming mode.");
+            }
+            pollStateDone();
+        }
+
+    }
+
+    private void setRssiDefaultValues() {
+        rssi = 99;
+    }
+
+    /**
+     * A complete "service state" from our perspective is
+     * composed of a handful of separate requests to the radio.
+     *
+     * We make all of these requests at once, but then abandon them
+     * and start over again if the radio notifies us that some
+     * event has changed
+     */
+
+    private void
+    pollState() {
+        pollingContext = new int[1];
+        pollingContext[0] = 0;
+
+        switch (cm.getRadioState()) {
+        case RADIO_UNAVAILABLE:
+            newSS.setStateOutOfService();
+            newCellLoc.setStateInvalid();
+            setRssiDefaultValues();
+            mGotCountryCode = false;
+
+            pollStateDone();
+            break;
+
+        case RADIO_OFF:
+            newSS.setStateOff();
+            newCellLoc.setStateInvalid();
+            setRssiDefaultValues();
+            mGotCountryCode = false;
+
+            pollStateDone();
+            break;
+
+        case SIM_NOT_READY:
+        case SIM_LOCKED_OR_ABSENT:
+        case SIM_READY:
+            log("Radio Technology Change ongoing, setting SS to off");
+            newSS.setStateOff();
+            newCellLoc.setStateInvalid();
+            setRssiDefaultValues();
+            mGotCountryCode = false;
+
+            pollStateDone();
+            break;
+
+        default:
+            // Issue all poll-related commands at once
+            // then count down the responses, which
+            // are allowed to arrive out-of-order
+
+            pollingContext[0]++;
+        //RIL_REQUEST_OPERATOR is necessary for CDMA
+        cm.getOperator(
+                obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
+
+        pollingContext[0]++;
+        //RIL_REQUEST_REGISTRATION_STATE is necessary for CDMA
+        cm.getRegistrationState(
+                obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, pollingContext));
+
+        pollingContext[0]++;
+        //RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE necessary for CDMA
+        cm.getNetworkSelectionMode(
+                obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA, pollingContext));
+        break;
+        }
+    }
+
+    private static String networkTypeToString(int type) {
+        String ret = "unknown";
+
+        switch (type) {
+        case DATA_ACCESS_CDMA_IS95A:
+        case DATA_ACCESS_CDMA_IS95B:
+            ret = "CDMA";
+            break;
+        case DATA_ACCESS_CDMA_1xRTT:
+            ret = "CDMA - 1xRTT";
+            break;
+        case DATA_ACCESS_CDMA_EvDo_0:
+            ret = "CDMA - EvDo rev. 0";
+            break;
+        case DATA_ACCESS_CDMA_EvDo_A:
+            ret = "CDMA - EvDo rev. A";
+            break;
+        default:
+            if (DBG) {
+                Log.e(LOG_TAG, "Wrong network. Can not return a string.");
+            }
+        break;
+        }
+
+        return ret;
+    }
+
+    private void
+    pollStateDone() {
+        if (DBG) {
+            Log.d(LOG_TAG, "Poll ServiceState done: " +
+                    " oldSS=[" + ss );
+            Log.d(LOG_TAG, "Poll ServiceState done: " +
+                    " newSS=[" + newSS);
+        }
+
+        boolean hasRegistered =
+            ss.getState() != ServiceState.STATE_IN_SERVICE
+            && newSS.getState() == ServiceState.STATE_IN_SERVICE;
+
+        boolean hasDeregistered =
+            ss.getState() == ServiceState.STATE_IN_SERVICE
+            && newSS.getState() != ServiceState.STATE_IN_SERVICE;
+
+        boolean hasCdmaDataConnectionAttached =
+            (this.cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    && this.cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    && this.cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_A)
+                    && (this.newCdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    || this.newCdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    || this.newCdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_A);
+
+        boolean hasCdmaDataConnectionDetached =
+            (this.cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    || this.cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    || this.cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
+                    && (this.newCdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    && this.newCdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    && this.newCdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_A);
+
+        boolean hasCdmaDataConnectionChanged =
+                       cdmaDataConnectionState != newCdmaDataConnectionState;
+
+        boolean hasNetworkTypeChanged = networkType != newNetworkType;
+
+        boolean hasChanged = !newSS.equals(ss);
+
+        boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
+
+        boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
+
+        boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
+
+        ServiceState tss;
+        tss = ss;
+        ss = newSS;
+        newSS = tss;
+        // clean slate for next time
+        newSS.setStateOutOfService();
+
+        CdmaCellLocation tcl = cellLoc;
+        cellLoc = newCellLoc;
+        newCellLoc = tcl;
+
+        cdmaDataConnectionState = newCdmaDataConnectionState;
+        networkType = newNetworkType;
+
+        newSS.setStateOutOfService(); // clean slate for next time
+
+        if (hasNetworkTypeChanged) {
+            phone.setSystemProperty(PROPERTY_DATA_NETWORK_TYPE,
+                    networkTypeToString(networkType));
+        }
+
+        if (hasRegistered) {
+            Checkin.updateStats(phone.getContext().getContentResolver(),
+                    Checkin.Stats.Tag.PHONE_CDMA_REGISTERED, 1, 0.0);
+            networkAttachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasChanged) {
+            String operatorNumeric;
+
+            phone.setSystemProperty(PROPERTY_OPERATOR_ALPHA,
+                    ss.getOperatorAlphaLong());
+
+            operatorNumeric = ss.getOperatorNumeric();
+            phone.setSystemProperty(PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
+
+            if (operatorNumeric == null) {
+                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, "");
+            } else {
+                String iso = "";
+                try{
+                    iso = MccTable.countryCodeForMcc(Integer.parseInt(
+                            operatorNumeric.substring(0,3)));
+                } catch ( NumberFormatException ex){
+                    Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+                } catch ( StringIndexOutOfBoundsException ex) {
+                    Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+                }
+
+                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, iso);
+                mGotCountryCode = true;
+            }
+
+            phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
+                    ss.getRoaming() ? "true" : "false");
+            phone.setSystemProperty(PROPERTY_OPERATOR_ISMANUAL,
+                    ss.getIsManualSelection() ? "true" : "false");
+
+            updateSpnDisplay();
+            phone.notifyServiceStateChanged(ss);
+        }
+
+        if (hasCdmaDataConnectionAttached) {
+            cdmaDataConnectionAttachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasCdmaDataConnectionDetached) {
+            cdmaDataConnectionDetachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasCdmaDataConnectionChanged) {
+            phone.notifyDataConnection(null);
+        }
+
+        if (hasRoamingOn) {
+            roamingOnRegistrants.notifyRegistrants();
+        }
+
+        if (hasRoamingOff) {
+            roamingOffRegistrants.notifyRegistrants();
+        }
+
+        if (hasLocationChanged) {
+            phone.notifyLocationChanged();
+        }
+    }
+
+    /**
+     * Returns a TimeZone object based only on parameters from the NITZ string.
+     */
+    private TimeZone getNitzTimeZone(int offset, boolean dst, long when) {
+        TimeZone guess = findTimeZone(offset, dst, when);
+        if (guess == null) {
+            // Couldn't find a proper timezone.  Perhaps the DST data is wrong.
+            guess = findTimeZone(offset, !dst, when);
+        }
+        if (DBG) {
+            Log.d(LOG_TAG, "getNitzTimeZone returning "
+                    + (guess == null ? guess : guess.getID()));
+        }
+        return guess;
+    }
+
+    private TimeZone findTimeZone(int offset, boolean dst, long when) {
+        int rawOffset = offset;
+        if (dst) {
+            rawOffset -= 3600000;
+        }
+        String[] zones = TimeZone.getAvailableIDs(rawOffset);
+        TimeZone guess = null;
+        Date d = new Date(when);
+        for (String zone : zones) {
+            TimeZone tz = TimeZone.getTimeZone(zone);
+            if (tz.getOffset(when) == offset &&
+                    tz.inDaylightTime(d) == dst) {
+                guess = tz;
+                break;
+            }
+        }
+
+        return guess;
+    }
+
+    private void
+    queueNextSignalStrengthPoll() {
+        if (dontPollSignalStrength || (cm.getRadioState().isGsm())) {
+            // The radio is telling us about signal strength changes
+            // we don't have to ask it
+            return;
+        }
+
+        Message msg;
+
+        msg = obtainMessage();
+        msg.what = EVENT_POLL_SIGNAL_STRENGTH;
+
+        // TODO Done't poll signal strength if screen is off
+        sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
+    }
+
+    /**
+     *  send signal-strength-changed notification if rssi changed
+     *  Called both for solicited and unsolicited signal stength updates
+     */
+    private void
+    onSignalStrengthResult(AsyncResult ar) {
+        int oldRSSI = rssi;
+
+        if (ar.exception != null) {
+            // 99 = unknown
+            // most likely radio is resetting/disconnected
+            rssi = 99;
+        } else {
+            int[] ints = (int[])ar.result;
+
+            // bug 658816 seems to be a case where the result is 0-length
+            if (ints.length != 0) {
+                rssi = ints[0];
+            } else {
+                Log.e(LOG_TAG, "Bogus signal strength response");
+                rssi = 99;
+            }
+        }
+
+        if (rssi != oldRSSI) {
+            try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
+                  // POLL_PERIOD_MILLIS) during Radio Technology Change)
+                phone.notifySignalStrength();
+           } catch (NullPointerException ex) {
+                log("onSignalStrengthResult() Phone already destroyed: " + ex 
+                        + "Signal Stranth not notified");
+           }
+        }
+    }
+
+
+    private int radioTechnologyToServiceState(int code) {
+        int retVal = ServiceState.RADIO_TECHNOLOGY_UNKNOWN;
+        switch(code) {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+            break;
+        case 6:
+            retVal = ServiceState.RADIO_TECHNOLOGY_1xRTT;
+            break;
+        case 7:
+            retVal = ServiceState.RADIO_TECHNOLOGY_EVDO_0;
+            break;
+        case 8:
+            retVal = ServiceState.RADIO_TECHNOLOGY_EVDO_A;
+            break;
+        default:
+            Log.e(LOG_TAG, "Wrong radioTechnology code.");
+        break;
+        }
+        return(retVal);
+    }
+
+    /** code is registration state 0-5 from TS 27.007 7.2 */
+    private int
+    regCodeToServiceState(int code) {
+        switch (code) {
+        case 0: // Not searching and not registered
+            return ServiceState.STATE_OUT_OF_SERVICE;
+        case 1:
+            return ServiceState.STATE_IN_SERVICE;
+        case 2: // 2 is "searching", fall through
+        case 3: // 3 is "registration denied", fall through
+        case 4: // 4 is "unknown" no vaild in current baseband
+            return ServiceState.STATE_OUT_OF_SERVICE;
+        case 5:// fall through
+        case 6:
+            // Registered and: roaming (5) or roaming affiliates (6)
+            return ServiceState.STATE_IN_SERVICE;
+
+        default:
+            Log.w(LOG_TAG, "unexpected service state " + code);
+        return ServiceState.STATE_OUT_OF_SERVICE;
+        }
+    }
+
+    /**
+     * @return The current CDMA data connection state. ServiceState.RADIO_TECHNOLOGY_1xRTT or
+     * ServiceState.RADIO_TECHNOLOGY_EVDO is the same as "attached" and
+     * ServiceState.RADIO_TECHNOLOGY_UNKNOWN is the same as detached.
+     */
+    /*package*/ int getCurrentCdmaDataConnectionState() {
+        return cdmaDataConnectionState;
+    }
+
+    /**
+     * code is registration state 0-5 from TS 27.007 7.2
+     * returns true if registered roam, false otherwise
+     */
+    private boolean
+    regCodeIsRoaming (int code) {
+        // 5 is  "in service -- roam"
+        return 5 == code;
+    }
+
+    /**
+     * Set roaming state when cdmaRoaming is true and ons is different from spn
+     * @param cdmaRoaming TS 27.007 7.2 CREG registered roaming
+     * @param s ServiceState hold current ons
+     * @return true for roaming state set
+     */
+    private
+    boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) {
+        String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
+
+        String onsl = s.getOperatorAlphaLong();
+        String onss = s.getOperatorAlphaShort();
+
+        boolean equalsOnsl = onsl != null && spn.equals(onsl);
+        boolean equalsOnss = onss != null && spn.equals(onss);
+
+        return cdmaRoaming && !(equalsOnsl || equalsOnss);
+    }
+
+    private boolean getAutoTime() {
+        try {
+            return Settings.System.getInt(phone.getContext().getContentResolver(),
+                    Settings.System.AUTO_TIME) > 0;
+        } catch (SettingNotFoundException snfe) {
+            return true;
+        }
+    }
+
+    /**
+     * @return true if phone is camping on a technology
+     * that could support voice and data simultaneously.
+     */
+    boolean isConcurrentVoiceAndData() {
+
+        // Note: it needs to be confirmed which CDMA network types
+        // can support voice and data calls concurrently.
+        // For the time-being, the return value will be false.
+        return false;
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java b/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java
new file mode 100644
index 0000000..c226b62
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.content.Context;
+import android.os.*;
+import android.util.Log;
+
+import com.android.internal.telephony.*;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ *
+ * {@hide}
+ *
+ */
+public final class FeatureCode  extends Handler implements MmiCode {
+    static final String LOG_TAG = "CDMA";
+
+    //***** Constants
+
+    // Call Forwarding
+    static final String FC_CF_ACTIVATE            = "72";
+    static final String FC_CF_DEACTIVATE          = "73";
+    static final String FC_CF_FORWARD_TO_NUMBER   = "56";
+
+    // Call Forwarding Busy Line
+    static final String FC_CFBL_ACTIVATE          = "90";
+    static final String FC_CFBL_DEACTIVATE        = "91";
+    static final String FC_CFBL_FORWARD_TO_NUMBER = "40";
+
+    // Call Forwarding Don't Answer
+    static final String FC_CFDA_ACTIVATE          = "92";
+    static final String FC_CFDA_DEACTIVATE        = "93";
+    static final String FC_CFDA_FORWARD_TO_NUMBER = "42";
+
+    // Cancel Call Waiting
+    static final String FC_CCW                    = "70";
+
+    // Usage Sensitive Three-way Calling
+    static final String FC_3WC                    = "71";
+
+    // Do Not Disturb
+    static final String FC_DND_ACTIVATE           = "78";
+    static final String FC_DND_DEACTIVATE         = "79";
+
+    // Who Called Me?
+    static final String FC_WHO                    = "51";
+
+    // Rejection of Undesired Annoying Calls
+    static final String FC_RUAC_ACTIVATE          = "60";
+    static final String FC_RUAC_DEACTIVATE        = "80";
+
+    // Calling Number Delivery
+    // Calling Number Identification Presentation
+    static final String FC_CNIP                   = "65";
+    // Calling Number Identification Restriction
+    static final String FC_CNIR                   = "85";
+
+
+    //***** Event Constants
+
+    static final int EVENT_SET_COMPLETE         = 1;
+    static final int EVENT_CDMA_FLASH_COMPLETED = 2;
+
+
+    //***** Instance Variables
+
+    CDMAPhone phone;
+    Context context;
+
+    String action;              // '*' in CDMA
+    String sc;                  // Service Code
+    String poundString;         // Entire Flash string
+    String dialingNumber;
+
+    /** Set to true in processCode, not at newFromDialString time */
+
+    State state = State.PENDING;
+    CharSequence message;
+
+    //***** Class Variables
+
+
+    // Flash Code Pattern
+
+    static Pattern sPatternSuppService = Pattern.compile(
+        "((\\*)(\\d{2,3})(#?)([^*#]*)?)(.*)");
+/*       1  2    3       4   5         6
+
+         1 = Full string up to and including #
+         2 = action
+         3 = service code
+         4 = separator
+         5 = dialing number
+*/
+
+    static final int MATCH_GROUP_POUND_STRING   = 1;
+    static final int MATCH_GROUP_ACTION_STRING  = 2;
+    static final int MATCH_GROUP_SERVICE_CODE   = 3;
+    static final int MATCH_GROUP_DIALING_NUMBER = 5;
+
+
+    //***** Public Class methods
+
+    /**
+     * Some dial strings in CDMA are defined to do non-call setup
+     * things, such as set supplementary service settings (eg, call
+     * forwarding). These are generally referred to as "Feature Codes".
+     * We look to see if the dial string contains a valid Feature code (potentially
+     * with a dial string at the end as well) and return info here.
+     *
+     * If the dial string contains no Feature code, we return an instance with
+     * only "dialingNumber" set
+     *
+     * Please see also S.R0006-000-A v2.0 "Wireless Features Description"
+     */
+
+    static FeatureCode newFromDialString(String dialString, CDMAPhone phone) {
+        Matcher m;
+        FeatureCode ret = null;
+
+        m = sPatternSuppService.matcher(dialString);
+
+        // Is this formatted like a standard supplementary service code?
+        if (m.matches()) {
+            ret = new FeatureCode(phone);
+            ret.poundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
+            ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION_STRING));
+            ret.sc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
+            ret.dialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
+        }
+
+        return ret;
+    }
+
+    //***** Private Class methods
+
+    /** make empty strings be null.
+     *  Java regexp returns empty strings for empty groups
+     */
+    private static String makeEmptyNull (String s) {
+        if (s != null && s.length() == 0) return null;
+
+        return s;
+    }
+
+    /** returns true of the string is empty or null */
+    private static boolean isEmptyOrNull(CharSequence s) {
+        return s == null || (s.length() == 0);
+    }
+
+    static boolean isServiceCodeCallForwarding(String sc) {
+        return sc != null &&
+                (sc.equals(FC_CF_ACTIVATE)
+                || sc.equals(FC_CF_DEACTIVATE) || sc.equals(FC_CF_FORWARD_TO_NUMBER)
+                || sc.equals(FC_CFBL_ACTIVATE) || sc.equals(FC_CFBL_DEACTIVATE)
+                || sc.equals(FC_CFBL_FORWARD_TO_NUMBER) || sc.equals(FC_CFDA_ACTIVATE)
+                || sc.equals(FC_CFDA_DEACTIVATE) || sc.equals(FC_CFDA_FORWARD_TO_NUMBER));
+    }
+
+    static boolean isServiceCodeCallWaiting(String sc) {
+        return sc != null && sc.equals(FC_CCW);
+    }
+
+    static boolean isServiceCodeThreeWayCalling(String sc) {
+        return sc != null && sc.equals(FC_3WC);
+    }
+
+    static boolean isServiceCodeAnnoyingCalls(String sc) {
+        return sc != null &&
+                (sc.equals(FC_RUAC_ACTIVATE)
+                || sc.equals(FC_RUAC_DEACTIVATE));
+    }
+
+    static boolean isServiceCodeCallingNumberDelivery(String sc) {
+        return sc != null &&
+                (sc.equals(FC_CNIP)
+                || sc.equals(FC_CNIR));
+    }
+
+    static boolean isServiceCodeDoNotDisturb(String sc) {
+        return sc != null &&
+                (sc.equals(FC_DND_ACTIVATE)
+                || sc.equals(FC_DND_DEACTIVATE));
+    }
+
+
+    //***** Constructor
+
+    FeatureCode (CDMAPhone phone) {
+        super(phone.getHandler().getLooper());
+        this.phone = phone;
+        this.context = phone.getContext();
+    }
+
+
+    //***** MmiCode implementation
+
+    public State getState() {
+        return state;
+    }
+
+    public CharSequence getMessage() {
+        return message;
+    }
+
+    // inherited javadoc suffices
+    public void cancel() {
+        //Not used here
+    }
+
+    public boolean isCancelable() {
+        Log.e(LOG_TAG, "isCancelable: not used in CDMA");
+        return false;
+    }
+
+    public boolean isUssdRequest() {
+        Log.e(LOG_TAG, "isUssdRequest: not used in CDMA");
+        return false;
+    }
+
+    /** Process a Flash Code...anything that isn't a dialing number */
+    void processCode () {
+        Log.d(LOG_TAG, "send feature code...");
+        phone.mCM.sendCDMAFeatureCode(this.poundString,
+                obtainMessage(EVENT_CDMA_FLASH_COMPLETED));
+    }
+
+    /** Called from CDMAPhone.handleMessage; not a Handler subclass */
+    public void handleMessage (Message msg) {
+        AsyncResult ar;
+
+        switch (msg.what) {
+        case EVENT_SET_COMPLETE:
+            ar = (AsyncResult) (msg.obj);
+            onSetComplete(ar);
+            break;
+        case EVENT_CDMA_FLASH_COMPLETED:
+            ar = (AsyncResult) (msg.obj);
+
+            if (ar.exception != null) {
+                state = State.FAILED;
+                message = context.getText(com.android.internal.R.string.fcError);
+            } else {
+                state = State.COMPLETE;
+                message = context.getText(com.android.internal.R.string.fcComplete);
+            }
+            phone.onFeatureCodeDone(this);
+            break;
+        }
+    }
+
+
+    //***** Private instance methods
+
+    private CharSequence getScString() {
+        if (sc != null) {
+            if (isServiceCodeCallForwarding(sc)) {
+                return context.getText(com.android.internal.R.string.CfMmi);
+            } else if (isServiceCodeCallWaiting(sc)) {
+                return context.getText(com.android.internal.R.string.CwMmi);
+            } else if (sc.equals(FC_CNIP)) {
+                return context.getText(com.android.internal.R.string.CnipMmi);
+            } else if (sc.equals(FC_CNIR)) {
+                return context.getText(com.android.internal.R.string.CnirMmi);
+            } else if (isServiceCodeThreeWayCalling(sc)) {
+                return context.getText(com.android.internal.R.string.ThreeWCMmi);
+            } else if (isServiceCodeAnnoyingCalls(sc)) {
+                return context.getText(com.android.internal.R.string.RuacMmi);
+            } else if (isServiceCodeCallingNumberDelivery(sc)) {
+                return context.getText(com.android.internal.R.string.CndMmi);
+            } else if (isServiceCodeDoNotDisturb(sc)) {
+                return context.getText(com.android.internal.R.string.DndMmi);
+            }
+        }
+
+        return "";
+    }
+
+    private void onSetComplete(AsyncResult ar){
+        StringBuilder sb = new StringBuilder(getScString());
+        sb.append("\n");
+
+        if (ar.exception != null) {
+            state = State.FAILED;
+            sb.append(context.getText(com.android.internal.R.string.mmiError));
+        } else {
+            state = State.FAILED;
+            sb.append(context.getText(com.android.internal.R.string.mmiError));
+        }
+
+        message = sb;
+        phone.onFeatureCodeDone(this);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
similarity index 65%
copy from telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
copy to telephony/java/com/android/internal/telephony/cdma/RuimCard.java
index a4cded9..9d9f479 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
@@ -14,85 +14,90 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony.cdma;
 
 import android.os.AsyncResult;
-import android.os.RemoteException;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RegistrantList;
+import android.os.RemoteException;
 import android.util.Log;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyProperties;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
+import android.app.ActivityManagerNative;
 import android.content.Intent;
 import android.content.res.Configuration;
-import android.app.ActivityManagerNative;
 
 import static android.Manifest.permission.READ_PHONE_STATE;
 
 /**
+ * Note: this class shares common code with SimCard, consider a base class to minimize code
+ * duplication.
  * {@hide}
  */
-public final class GsmSimCard extends Handler implements SimCard {
-    static final String LOG_TAG="GSM";
-    
+public final class RuimCard extends Handler implements IccCard {
+    static final String LOG_TAG="CDMA";
+
     //***** Instance Variables
     private static final boolean DBG = true;
 
-    private GSMPhone phone;
-    private CommandsInterface.SimStatus status = null;
-    private boolean mSimPinLocked = true; // Default to locked
-    private boolean mSimFdnEnabled = false; // Default to disabled.
-                                            // Will be updated when SIM_READY.
+    private CDMAPhone phone;
+
+    private CommandsInterface.IccStatus status = null;
     private boolean mDesiredPinLocked;
     private boolean mDesiredFdnEnabled;
+    private boolean mRuimPinLocked = true; // default to locked
+    private boolean mRuimFdnEnabled = false; // Default to disabled.
+                                            // Will be updated when RUIM_READY.
+//    //***** Constants
 
-    //***** Constants
-
-    // FIXME I hope this doesn't conflict with the Dialer's notifications
-    static final int NOTIFICATION_ID_SIM_STATUS = 33456;
+//    // FIXME I hope this doesn't conflict with the Dialer's notifications
+//    Nobody is using this at the moment
+//    static final int NOTIFICATION_ID_ICC_STATUS = 33456;
 
     //***** Event Constants
 
-    static final int EVENT_SIM_LOCKED_OR_ABSENT = 1;
-    static final int EVENT_GET_SIM_STATUS_DONE = 2;
+    static final int EVENT_RUIM_LOCKED_OR_ABSENT = 1;
+    static final int EVENT_GET_RUIM_STATUS_DONE = 2;
     static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 3;
     static final int EVENT_PINPUK_DONE = 4;
     static final int EVENT_REPOLL_STATUS_DONE = 5;
-    static final int EVENT_SIM_READY = 6;
+    static final int EVENT_RUIM_READY = 6;
     static final int EVENT_QUERY_FACILITY_LOCK_DONE = 7;
     static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 8;
-    static final int EVENT_CHANGE_SIM_PASSWORD_DONE = 9;
+    static final int EVENT_CHANGE_RUIM_PASSWORD_DONE = 9;
     static final int EVENT_QUERY_FACILITY_FDN_DONE = 10;
     static final int EVENT_CHANGE_FACILITY_FDN_DONE = 11;
 
 
     //***** Constructor
 
-    GsmSimCard(GSMPhone phone)
-    {
+    RuimCard(CDMAPhone phone) {
         this.phone = phone;
 
-        phone.mCM.registerForSIMLockedOrAbsent(
-                        this, EVENT_SIM_LOCKED_OR_ABSENT, null);
+        phone.mCM.registerForRUIMLockedOrAbsent(
+                        this, EVENT_RUIM_LOCKED_OR_ABSENT, null);
 
         phone.mCM.registerForOffOrNotAvailable(
                         this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
 
-        phone.mCM.registerForSIMReady(
-                        this, EVENT_SIM_READY, null);
+        phone.mCM.registerForRUIMReady(
+                        this, EVENT_RUIM_READY, null);
 
         updateStateProperty();
     }
-    
-    //***** SimCard implementation
+
+    //***** RuimCard implementation
 
     public State
-    getState()
-    {
+    getState() {
         if (status == null) {
             switch(phone.mCM.getRadioState()) {
                 /* This switch block must not return anything in
@@ -101,36 +106,49 @@
                  */
                 case RADIO_OFF:
                 case RADIO_UNAVAILABLE:
-                case SIM_NOT_READY:
+                case RUIM_NOT_READY:
                     return State.UNKNOWN;
-                case SIM_LOCKED_OR_ABSENT:
+                case RUIM_LOCKED_OR_ABSENT:
                     //this should be transient-only
                     return State.UNKNOWN;
-                case SIM_READY:
+                case RUIM_READY:
                     return State.READY;
+                case NV_READY:
+                case NV_NOT_READY:
+                    return State.ABSENT;
             }
         } else {
             switch (status) {
-                case SIM_ABSENT:            return State.ABSENT;
-                case SIM_NOT_READY:         return State.UNKNOWN;
-                case SIM_READY:             return State.READY;
-                case SIM_PIN:               return State.PIN_REQUIRED;
-                case SIM_PUK:               return State.PUK_REQUIRED;
-                case SIM_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
+                case ICC_ABSENT:            return State.ABSENT;
+                case ICC_NOT_READY:         return State.UNKNOWN;
+                case ICC_READY:             return State.READY;
+                case ICC_PIN:               return State.PIN_REQUIRED;
+                case ICC_PUK:               return State.PUK_REQUIRED;
+                case ICC_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
             }
         }
 
-        Log.e(LOG_TAG, "GsmSimCard.getState(): case should never be reached");
+        Log.e(LOG_TAG, "RuimCard.getState(): case should never be reached");
         return State.UNKNOWN;
     }
 
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForRUIMLockedOrAbsent(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        phone.mCM.unregisterForRUIMReady(this);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimCard finalized");
+    }
+
     private RegistrantList absentRegistrants = new RegistrantList();
     private RegistrantList pinLockedRegistrants = new RegistrantList();
     private RegistrantList networkLockedRegistrants = new RegistrantList();
 
 
-    public void registerForAbsent(Handler h, int what, Object obj)
-    {
+    public void registerForAbsent(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         absentRegistrants.add(r);
@@ -139,9 +157,9 @@
             r.notifyRegistrant();
         }
     }
-    
+
     public void unregisterForAbsent(Handler h) {
-    	absentRegistrants.remove(h);
+        absentRegistrants.remove(h);
     }
 
     public void registerForNetworkLocked(Handler h, int what, Object obj) {
@@ -155,11 +173,10 @@
     }
 
     public void unregisterForNetworkLocked(Handler h) {
-    	networkLockedRegistrants.remove(h);
+        networkLockedRegistrants.remove(h);
     }
-    
-    public void registerForLocked(Handler h, int what, Object obj)
-    {
+
+    public void registerForLocked(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         pinLockedRegistrants.add(r);
@@ -169,50 +186,41 @@
         }
     }
 
-    public void unregisterForLocked(Handler h)
-    {
+    public void unregisterForLocked(Handler h) {
         pinLockedRegistrants.remove(h);
     }
 
-
-    public void supplyPin (String pin, Message onComplete)
-    {
-        phone.mCM.supplySimPin(pin, 
-                            obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    public void supplyPin (String pin, Message onComplete) {
+        phone.mCM.supplyIccPin(pin, obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyPuk (String puk, String newPin, Message onComplete)
-    {
-        phone.mCM.supplySimPuk(puk, newPin,
-                        obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    public void supplyPuk (String puk, String newPin, Message onComplete) {
+        phone.mCM.supplyIccPuk(puk, newPin, obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPin2 (String pin2, Message onComplete)
-    {
-        phone.mCM.supplySimPin2(pin2, 
-                        obtainMessage(EVENT_PINPUK_DONE, onComplete));
+
+    public void supplyPin2 (String pin2, Message onComplete) {
+        phone.mCM.supplyIccPin2(pin2, obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPuk2 (String puk2, String newPin2, Message onComplete)
-    {
-        phone.mCM.supplySimPuk2(puk2, newPin2,
+
+    public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
+        phone.mCM.supplyIccPuk2(puk2, newPin2, obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    }
+
+    public void supplyNetworkDepersonalization (String pin, Message onComplete) {
+        if(DBG) log("Network Despersonalization: " + pin);
+        phone.mCM.supplyNetworkDepersonalization(pin,
                 obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyNetworkDepersonalization (String pin, Message onComplete)
-    {
-        if(DBG) log("Network Despersonalization: " + pin);
-        phone.mCM.supplyNetworkDepersonalization(pin,
-                        obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    public boolean getIccLockEnabled() {
+       return mRuimPinLocked;
     }
 
-    public boolean getSimLockEnabled() {
-       return mSimPinLocked;
+    public boolean getIccFdnEnabled() {
+       return mRuimFdnEnabled;
     }
 
-    public boolean getSimFdnEnabled() {
-       return mSimFdnEnabled;
-    }
-
-    public void setSimLockEnabled (boolean enabled,
+    public void setIccLockEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -226,7 +234,7 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
     }
 
-    public void setSimFdnEnabled (boolean enabled,
+    public void setIccFdnEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -241,24 +249,22 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
     }
 
-    public void changeSimLockPassword(String oldPassword, String newPassword,
+    public void changeIccLockPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin1 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin(oldPassword, newPassword,
-                obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
-
+        phone.mCM.changeIccPin(oldPassword, newPassword,
+                obtainMessage(EVENT_CHANGE_RUIM_PASSWORD_DONE, onComplete));
     }
 
-    public void changeSimFdnPassword(String oldPassword, String newPassword,
+    public void changeIccFdnPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin2 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin2(oldPassword, newPassword,
-                obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
-
+        phone.mCM.changeIccPin2(oldPassword, newPassword,
+                obtainMessage(EVENT_CHANGE_RUIM_PASSWORD_DONE, onComplete));
     }
 
-    public String getServiceProviderName () {
-        return phone.mSIMRecords.getServiceProviderName();
+    public String getServiceProviderName() {
+        return phone.mRuimRecords.getServiceProviderName();
     }
 
     //***** Handler implementation
@@ -273,13 +279,15 @@
 
         switch (msg.what) {
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
+                Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
                 status = null;
                 updateStateProperty();
-                broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_NOT_READY, null);
+                broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_NOT_READY, null);
                 break;
-            case EVENT_SIM_READY:
+            case EVENT_RUIM_READY:
+                Log.d(LOG_TAG, "Event EVENT_RUIM_READY Received");
                 //TODO: put facility read in SIM_READY now, maybe in REG_NW
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_RUIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
@@ -287,18 +295,21 @@
                         CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
                 break;
-            case EVENT_SIM_LOCKED_OR_ABSENT:
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+            case EVENT_RUIM_LOCKED_OR_ABSENT:
+                Log.d(LOG_TAG, "Event EVENT_RUIM_LOCKED_OR_ABSENT Received");
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_RUIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
                 break;
-            case EVENT_GET_SIM_STATUS_DONE:
+            case EVENT_GET_RUIM_STATUS_DONE:
+                Log.d(LOG_TAG, "Event EVENT_GET_RUIM_STATUS_DONE Received");
                 ar = (AsyncResult)msg.obj;
 
-                getSimStatusDone(ar);
+                getRuimStatusDone(ar);
                 break;
             case EVENT_PINPUK_DONE:
+                Log.d(LOG_TAG, "Event EVENT_PINPUK_DONE Received");
                 // a PIN/PUK/PIN2/PUK2/Network Personalization
                 // request has completed. ar.userObj is the response Message
                 // Repoll before returning
@@ -306,33 +317,37 @@
                 // TODO should abstract these exceptions
                 AsyncResult.forMessage(((Message)ar.userObj)).exception
                                                     = ar.exception;
-                phone.mCM.getSimStatus(
+                phone.mCM.getIccStatus(
                     obtainMessage(EVENT_REPOLL_STATUS_DONE, ar.userObj));
                 break;
             case EVENT_REPOLL_STATUS_DONE:
+                Log.d(LOG_TAG, "Event EVENT_REPOLL_STATUS_DONE Received");
                 // Finished repolling status after PIN operation
                 // ar.userObj is the response messaeg
                 // ar.userObj.obj is already an AsyncResult with an
                 // appropriate exception filled in if applicable
 
                 ar = (AsyncResult)msg.obj;
-                getSimStatusDone(ar);
+                getRuimStatusDone(ar);
                 ((Message)ar.userObj).sendToTarget();
                 break;
             case EVENT_QUERY_FACILITY_LOCK_DONE:
+                Log.d(LOG_TAG, "Event EVENT_QUERY_FACILITY_LOCK_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 onQueryFacilityLock(ar);
                 break;
             case EVENT_QUERY_FACILITY_FDN_DONE:
+                Log.d(LOG_TAG, "Event EVENT_QUERY_FACILITY_FDN_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 onQueryFdnEnabled(ar);
                 break;
             case EVENT_CHANGE_FACILITY_LOCK_DONE:
+                Log.d(LOG_TAG, "Event EVENT_CHANGE_FACILITY_LOCK_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 if (ar.exception == null) {
-                    mSimPinLocked = mDesiredPinLocked;
+                    mRuimPinLocked = mDesiredPinLocked;
                     if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: " +
-                            "mSimPinLocked= " + mSimPinLocked);
+                            "mRuimPinLocked= " + mRuimPinLocked);
                 } else {
                     Log.e(LOG_TAG, "Error change facility lock with exception "
                         + ar.exception);
@@ -342,12 +357,13 @@
                 ((Message)ar.userObj).sendToTarget();
                 break;
             case EVENT_CHANGE_FACILITY_FDN_DONE:
+                Log.d(LOG_TAG, "Event EVENT_CHANGE_FACILITY_FDN_DONE Received");
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception == null) {
-                    mSimFdnEnabled = mDesiredFdnEnabled;
+                    mRuimFdnEnabled = mDesiredFdnEnabled;
                     if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " +
-                            "mSimFdnEnabled=" + mSimFdnEnabled);
+                            "mRuimFdnEnabled=" + mRuimFdnEnabled);
                 } else {
                     Log.e(LOG_TAG, "Error change facility fdn with exception "
                             + ar.exception);
@@ -356,7 +372,8 @@
                                                     = ar.exception;
                 ((Message)ar.userObj).sendToTarget();
                 break;
-            case EVENT_CHANGE_SIM_PASSWORD_DONE:
+            case EVENT_CHANGE_RUIM_PASSWORD_DONE:
+                Log.d(LOG_TAG, "Event EVENT_CHANGE_RUIM_PASSWORD_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 if(ar.exception != null) {
                     Log.e(LOG_TAG, "Error in change sim password with exception"
@@ -367,15 +384,14 @@
                 ((Message)ar.userObj).sendToTarget();
                 break;
             default:
-                Log.e(LOG_TAG, "[GsmSimCard] Unknown Event " + msg.what);
+                Log.e(LOG_TAG, "[CdmaRuimCard] Unknown Event " + msg.what);
         }
     }
 
-
     //***** Private methods
 
     /**
-     * Interperate EVENT_QUERY_FACILITY_LOCK_DONE
+     * Interpret EVENT_QUERY_FACILITY_LOCK_DONE
      * @param ar is asyncResult of Query_Facility_Locked
      */
     private void onQueryFacilityLock(AsyncResult ar) {
@@ -386,15 +402,15 @@
 
         int[] ints = (int[])ar.result;
         if(ints.length != 0) {
-            mSimPinLocked = (0!=ints[0]);
-            if(DBG) log("Query facility lock : "  + mSimPinLocked);
+            mRuimPinLocked = (0!=ints[0]);
+            if(DBG) log("Query facility lock : "  + mRuimPinLocked);
         } else {
-            Log.e(LOG_TAG, "[GsmSimCard] Bogus facility lock response");
+            Log.e(LOG_TAG, "[CdmaRuimCard] Bogus facility lock response");
         }
     }
 
     /**
-     * Interperate EVENT_QUERY_FACILITY_LOCK_DONE
+     * Interpret EVENT_QUERY_FACILITY_LOCK_DONE
      * @param ar is asyncResult of Query_Facility_Locked
      */
     private void onQueryFdnEnabled(AsyncResult ar) {
@@ -405,15 +421,15 @@
 
         int[] ints = (int[])ar.result;
         if(ints.length != 0) {
-            mSimFdnEnabled = (0!=ints[0]);
-            if(DBG) log("Query facility lock : "  + mSimFdnEnabled);
+            mRuimFdnEnabled = (0!=ints[0]);
+            if(DBG) log("Query facility lock : "  + mRuimFdnEnabled);
         } else {
-            Log.e(LOG_TAG, "[GsmSimCard] Bogus facility lock response");
+            Log.e(LOG_TAG, "[CdmaRuimCard] Bogus facility lock response");
         }
     }
 
     private void
-    getSimStatusDone(AsyncResult ar) {
+    getRuimStatusDone(AsyncResult ar) {
         if (ar.exception != null) {
             Log.e(LOG_TAG,"Error getting SIM status. "
                     + "RIL_REQUEST_GET_SIM_STATUS should "
@@ -421,19 +437,19 @@
             return;
         }
 
-        CommandsInterface.SimStatus newStatus 
-            = (CommandsInterface.SimStatus)  ar.result;
+        CommandsInterface.IccStatus newStatus
+            = (CommandsInterface.IccStatus)  ar.result;
 
-        handleSimStatus(newStatus);
+        handleRuimStatus(newStatus);
     }
 
     private void
-    handleSimStatus(CommandsInterface.SimStatus newStatus) {
+    handleRuimStatus(CommandsInterface.IccStatus newStatus) {
         boolean transitionedIntoPinLocked;
         boolean transitionedIntoAbsent;
         boolean transitionedIntoNetworkLocked;
-        
-        SimCard.State oldState, newState;
+
+        RuimCard.State oldState, newState;
 
         oldState = getState();
         status = newStatus;
@@ -449,28 +465,28 @@
                 && newState == State.NETWORK_LOCKED);
 
         if (transitionedIntoPinLocked) {
-            if(DBG) log("Notify SIM pin or puk locked.");
+            if(DBG) log("Notify RUIM pin or puk locked.");
             pinLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED, 
+            broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_LOCKED,
                     (newState == State.PIN_REQUIRED) ?
                        INTENT_VALUE_LOCKED_ON_PIN : INTENT_VALUE_LOCKED_ON_PUK);
         } else if (transitionedIntoAbsent) {
-            if(DBG) log("Notify SIM missing.");
+            if(DBG) log("Notify RUIM missing.");
             absentRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_ABSENT, null);
+            broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_ABSENT, null);
         } else if (transitionedIntoNetworkLocked) {
-            if(DBG) log("Notify SIM network locked.");
+            if(DBG) log("Notify RUIM network locked.");
             networkLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED,
+            broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_LOCKED,
                   INTENT_VALUE_LOCKED_NETWORK);
         }
     }
 
-    public void broadcastSimStateChangedIntent(String value, String reason) {
+    public void broadcastRuimStateChangedIntent(String value, String reason) {
         Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         intent.putExtra(Phone.PHONE_NAME_KEY, phone.getPhoneName());
-        intent.putExtra(SimCard.INTENT_KEY_SIM_STATE, value);
-        intent.putExtra(SimCard.INTENT_KEY_LOCKED_REASON, reason);
+        intent.putExtra(RuimCard.INTENT_KEY_ICC_STATE, value);
+        intent.putExtra(RuimCard.INTENT_KEY_LOCKED_REASON, reason);
         if(DBG) log("Broadcasting intent SIM_STATE_CHANGED_ACTION " +  value
                 + " reason " + reason);
         ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE);
@@ -500,7 +516,7 @@
     }
 
     private void log(String msg) {
-        Log.d(LOG_TAG, "[GsmSimCard] " + msg);
+        Log.d(LOG_TAG, "[RuimCard] " + msg);
     }
 }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
new file mode 100644
index 0000000..9de6c42
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.os.*;
+import android.util.Log;
+
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccException;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccFileTypeMismatch;
+import com.android.internal.telephony.IccIoResult;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public final class RuimFileHandler extends IccFileHandler {
+    static final String LOG_TAG = "CDMA";
+
+    //***** Instance Variables
+
+    //***** Constructor
+    RuimFileHandler(CDMAPhone phone) {
+        super(phone);
+    }
+
+    public void dispose() {
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "RuimFileHandler finalized");
+    }
+
+    //***** Overridden from IccFileHandler
+
+    @Override
+    public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset,
+            int length, Message onLoaded) {
+        Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
+                onLoaded);
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, "img", 0, 0,
+                GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null, response);
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+
+        super.handleMessage(msg);
+    }
+
+    protected String getEFPath(int efid) {
+        // TODO(): Implement for CDMA EFs.
+        return getCommonIccEFPath(efid);
+    }
+
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[RuimFileHandler] " + msg);
+    }
+
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[RuimFileHandler] " + msg);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
new file mode 100644
index 0000000..78e89d5
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
@@ -0,0 +1,101 @@
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.internal.telephony.cdma;
+
+import android.content.pm.PackageManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.PhoneProxy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RuimPhoneBookInterfaceManager to provide an inter-process communication to
+ * access ADN-like SIM records.
+ */
+
+
+public class RuimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
+    static final String LOG_TAG = "CDMA";
+
+
+    Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+
+            switch(msg.what) {
+                default:
+                    mBaseHandler.handleMessage(msg);
+                    break;
+            }
+        }
+    };
+
+    public RuimPhoneBookInterfaceManager(CDMAPhone phone) {
+        super(phone);
+        adnCache = phone.mRuimRecords.getAdnCache();
+        //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
+    }
+
+    public void dispose() {
+        super.dispose();
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimPhoneBookInterfaceManager finalized");
+    }
+
+    public int[] getAdnRecordsSize(int efid) {
+        if (DBG) logd("getAdnRecordsSize: efid=" + efid);
+        synchronized(mLock) {
+            checkThread();
+            recordSize = new int[3];
+
+            //Using mBaseHandler, no difference in EVENT_GET_SIZE_DONE handling
+            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE);
+
+            phone.getIccFileHandler().getEFLinearRecordSize(efid, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to load from the RUIM");
+            }
+        }
+
+        return recordSize;
+    }
+
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[RuimPbInterfaceManager] " + msg);
+    }
+
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[RuimPbInterfaceManager] " + msg);
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
new file mode 100644
index 0000000..b18a3f1
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.util.Log;
+
+import static com.android.internal.telephony.TelephonyProperties.*;
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.AdnRecordLoader;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.cdma.RuimCard;
+import com.android.internal.telephony.gsm.MccTable;
+
+// can't be used since VoiceMailConstants is not public
+//import com.android.internal.telephony.gsm.VoiceMailConstants;
+import com.android.internal.telephony.IccException;
+import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+
+
+/**
+ * {@hide}
+ */
+public final class RuimRecords extends IccRecords {
+    static final String LOG_TAG = "CDMA";
+
+    private static final boolean DBG = true;
+
+    //***** Instance Variables
+    String imsi_m;
+    String mdn = null;  // My mobile number
+    String h_sid;
+    String h_nid;
+    String min2_min1;   // 10 digit MIN value MIN2+MIN1 NEWRIL:TODO currently unused
+
+    // is not initialized
+
+    //***** Event Constants
+
+    private static final int EVENT_RUIM_READY = 1;
+    private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
+    private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
+    private static final int EVENT_GET_ICCID_DONE = 5;
+    private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
+    private static final int EVENT_UPDATE_DONE = 14;
+    private static final int EVENT_GET_SST_DONE = 17;
+    private static final int EVENT_GET_ALL_SMS_DONE = 18;
+    private static final int EVENT_MARK_SMS_READ_DONE = 19;
+
+    private static final int EVENT_SMS_ON_RUIM = 21;
+    private static final int EVENT_GET_SMS_DONE = 22;
+
+    private static final int EVENT_RUIM_REFRESH = 31;
+
+    //***** Constructor
+
+    RuimRecords(CDMAPhone p) {
+        super(p);
+
+        adnCache = new AdnRecordCache(phone);
+
+        recordsRequested = false;  // No load request is made till SIM ready
+
+        // recordsToLoad is set to 0 because no requests are made yet
+        recordsToLoad = 0;
+
+
+        p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
+        p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        // NOTE the EVENT_SMS_ON_RUIM is not registered
+        p.mCM.setOnIccRefresh(this, EVENT_RUIM_REFRESH, null);
+
+        // Start off by setting empty state
+        onRadioOffOrNotAvailable();
+
+    }
+
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForRUIMReady(this);
+        phone.mCM.unregisterForOffOrNotAvailable( this);
+        phone.mCM.unSetOnIccRefresh(this);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimRecords finalized");
+    }
+
+    protected void onRadioOffOrNotAvailable() {
+        countVoiceMessages = 0;
+        mncLength = 0;
+        iccid = null;
+
+        adnCache.reset();
+
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null);
+
+        // recordsRequested is set to false indicating that the SIM
+        // read requests made so far are not valid. This is set to
+        // true only when fresh set of read requests are made.
+        recordsRequested = false;
+    }
+
+    //***** Public Methods
+
+    /** Returns null if RUIM is not yet ready */
+    public String getIMSI_M() {
+        return imsi_m;
+    }
+
+    public String getMdnNumber() {
+        return mdn;
+    }
+
+    public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
+        // In CDMA this is Operator/OEM dependent
+        AsyncResult.forMessage((onComplete)).exception =
+                new IccException("setVoiceMailNumber not implemented");
+        onComplete.sendToTarget();
+        Log.e(LOG_TAG, "method setVoiceMailNumber is not implemented");
+    }
+
+    /**
+     * Called by CCAT Service when REFRESH is received.
+     * @param fileChanged indicates whether any files changed
+     * @param fileList if non-null, a list of EF files that changed
+     */
+    public void onRefresh(boolean fileChanged, int[] fileList) {
+        if (fileChanged) {
+            // A future optimization would be to inspect fileList and
+            // only reload those files that we care about.  For now,
+            // just re-fetch all RUIM records that we cache.
+            fetchRuimRecords();
+        }
+    }
+
+    /** Returns the 5 or 6 digit MCC/MNC of the operator that
+     *  provided the RUIM card. Returns null of RUIM is not yet ready
+     */
+    String getRUIMOperatorNumeric() {
+        if (imsi_m == null) {
+            return null;
+        }
+
+        if (mncLength != 0) {
+            // Length = length of MCC + length of MNC
+            // TODO: change spec name
+            // length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
+            return imsi_m.substring(0, 3 + mncLength);
+        }
+
+        // Guess the MNC length based on the MCC if we don't
+        // have a valid value in ef[ad]
+
+        int mcc;
+
+        mcc = Integer.parseInt(imsi_m.substring(0,3));
+
+        return imsi_m.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
+    }
+
+    //***** Overridden from Handler
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+
+        byte data[];
+
+        boolean isRecordLoadResponse = false;
+
+        try { switch (msg.what) {
+            case EVENT_RUIM_READY:
+                onRuimReady();
+            break;
+
+            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
+                onRadioOffOrNotAvailable();
+            break;
+
+            case EVENT_GET_DEVICE_IDENTITY_DONE:
+                Log.d(LOG_TAG, "Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
+            break;
+
+            /* IO events */
+
+            case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
+                ar = (AsyncResult)msg.obj;
+                String localTemp[] = (String[])ar.result;
+                if (ar.exception != null) {
+                    break;
+                }
+
+                mdn    = localTemp[0];
+                h_sid  = localTemp[1];
+                h_nid  = localTemp[2];
+                if (localTemp.length >= 3) { // NEWRIL:TODO remove when new ril always returns min2_min1
+                    min2_min1 = localTemp[3];
+                }
+
+                Log.d(LOG_TAG, "MDN: " + mdn);
+
+            break;
+
+            case EVENT_GET_ICCID_DONE:
+                isRecordLoadResponse = true;
+
+                ar = (AsyncResult)msg.obj;
+                data = (byte[])ar.result;
+
+                if (ar.exception != null) {
+                    break;
+                }
+
+                iccid = IccUtils.bcdToString(data, 0, data.length);
+
+                Log.d(LOG_TAG, "iccid: " + iccid);
+
+            break;
+
+            case EVENT_UPDATE_DONE:
+                ar = (AsyncResult)msg.obj;
+                if (ar.exception != null) {
+                    Log.i(LOG_TAG, "RuimRecords update failed", ar.exception);
+                }
+            break;
+
+            case EVENT_GET_ALL_SMS_DONE:
+            case EVENT_MARK_SMS_READ_DONE:
+            case EVENT_SMS_ON_RUIM:
+            case EVENT_GET_SMS_DONE:
+                Log.w(LOG_TAG, "Event not supported: " + msg.what);
+                break;
+
+            // TODO: probably EF_CST should be read instead
+            case EVENT_GET_SST_DONE:
+                Log.d(LOG_TAG, "Event EVENT_GET_SST_DONE Received");
+            break;
+
+            case EVENT_RUIM_REFRESH:
+                isRecordLoadResponse = false;
+                ar = (AsyncResult)msg.obj;
+                if (ar.exception == null) {
+                    handleRuimRefresh((int[])(ar.result));
+                }
+                break;
+
+        }}catch (RuntimeException exc) {
+            // I don't want these exceptions to be fatal
+            Log.w(LOG_TAG, "Exception parsing RUIM record", exc);
+        } finally {
+            // Count up record load responses even if they are fails
+            if (isRecordLoadResponse) {
+                onRecordLoaded();
+            }
+        }
+    }
+
+    protected void onRecordLoaded() {
+        // One record loaded successfully or failed, In either case
+        // we need to update the recordsToLoad count
+        recordsToLoad -= 1;
+
+        if (recordsToLoad == 0 && recordsRequested == true) {
+            onAllRecordsLoaded();
+        } else if (recordsToLoad < 0) {
+            Log.e(LOG_TAG, "RuimRecords: recordsToLoad <0, programmer error suspected");
+            recordsToLoad = 0;
+        }
+    }
+
+    protected void onAllRecordsLoaded() {
+        Log.d(LOG_TAG, "RuimRecords: record load complete");
+
+        // Further records that can be inserted are Operator/OEM dependent
+
+        recordsLoadedRegistrants.notifyRegistrants(
+            new AsyncResult(null, null, null));
+        ((CDMAPhone) phone).mRuimCard.broadcastRuimStateChangedIntent(
+                RuimCard.INTENT_VALUE_ICC_LOADED, null);
+    }
+
+
+    //***** Private Methods
+
+    private void onRuimReady() {
+        /* broadcast intent ICC_READY here so that we can make sure
+          READY is sent before IMSI ready
+        */
+
+        ((CDMAPhone) phone).mRuimCard.broadcastRuimStateChangedIntent(
+                RuimCard.INTENT_VALUE_ICC_READY, null);
+
+        fetchRuimRecords();
+
+        phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
+
+    }
+
+    private void fetchRuimRecords() {
+        recordsRequested = true;
+
+        Log.v(LOG_TAG, "RuimRecords:fetchRuimRecords " + recordsToLoad);
+
+        phone.getIccFileHandler().loadEFTransparent(EF_ICCID,
+                obtainMessage(EVENT_GET_ICCID_DONE));
+        recordsToLoad++;
+
+        // Further records that can be inserted are Operator/OEM dependent
+    }
+
+    @Override
+    protected int getDisplayRule(String plmn) {
+        // TODO together with spn
+        return 0;
+    }
+
+    @Override
+    public void setVoiceMessageWaiting(int line, int countWaiting) {
+        if (line != 1) {
+            // only profile 1 is supported
+            return;
+        }
+
+        // range check
+        if (countWaiting < 0) {
+            countWaiting = -1;
+        } else if (countWaiting > 0xff) {
+            // C.S0015-B v2, 4.5.12
+            // range: 0-99
+            countWaiting = 0xff;
+        }
+        countVoiceMessages = countWaiting;
+
+        ((CDMAPhone) phone).notifyMessageWaitingIndicator();
+    }
+
+    private void handleRuimRefresh(int[] result) {
+        if (result == null || result.length == 0) {
+            if (DBG) log("handleRuimRefresh without input");
+            return;
+        }
+
+        switch ((result[0])) {
+            case CommandsInterface.SIM_REFRESH_FILE_UPDATED:
+ 		        if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED");
+                adnCache.reset();
+                fetchRuimRecords();
+                break;
+            case CommandsInterface.SIM_REFRESH_INIT:
+		        if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT");
+                // need to reload all files (that we care about)
+                fetchRuimRecords();
+                break;
+            case CommandsInterface.SIM_REFRESH_RESET:
+		        if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET");
+                phone.mCM.setRadioPower(false, null);
+                /* Note: no need to call setRadioPower(true).  Assuming the desired
+                * radio power state is still ON (as tracked by ServiceStateTracker),
+                * ServiceStateTracker will call setRadioPower when it receives the
+                * RADIO_STATE_CHANGED notification for the power off.  And if the
+                * desired power state has changed in the interim, we don't want to
+                * override it with an unconditional power on.
+                */
+                break;
+            default:
+                // unknown refresh operation
+		        if (DBG) log("handleRuimRefresh with unknown operation");
+                break;
+        }
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[RuimRecords] " + s);
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
new file mode 100644
index 0000000..9439359
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.telephony.cdma;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.SmsRawData;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
+
+/**
+ * RuimSmsInterfaceManager to provide an inter-process communication to
+ * access Sms in Ruim.
+ */
+public class RuimSmsInterfaceManager extends IccSmsInterfaceManager {
+    static final String LOG_TAG = "CDMA";
+    static final boolean DBG = true;
+
+    private final Object mLock = new Object();
+    private boolean mSuccess;
+    private List<SmsRawData> mSms;
+
+    private static final int EVENT_LOAD_DONE = 1;
+    private static final int EVENT_UPDATE_DONE = 2;
+
+    Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+
+            switch (msg.what) {
+                case EVENT_UPDATE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    synchronized (mLock) {
+                        mSuccess = (ar.exception == null);
+                        mLock.notifyAll();
+                    }
+                    break;
+                case EVENT_LOAD_DONE:
+                    ar = (AsyncResult)msg.obj;
+                    synchronized (mLock) {
+                        if (ar.exception == null) {
+                            mSms  = (List<SmsRawData>)
+                                    buildValidRawData((ArrayList<byte[]>) ar.result);
+                        } else {
+                            if(DBG) log("Cannot load Sms records");
+                            if (mSms != null)
+                                mSms.clear();
+                        }
+                        mLock.notifyAll();
+                    }
+                    break;
+            }
+        }
+    };
+
+    public RuimSmsInterfaceManager(CDMAPhone phone) {
+        super(phone);
+        mDispatcher = new CdmaSMSDispatcher(phone);
+    }
+
+    public void dispose() {
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimSmsInterfaceManager finalized");
+    }
+
+    /**
+     * Update the specified message on the RUIM.
+     *
+     * @param index record index of message to update
+     * @param status new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
+     * @param pdu the raw PDU to store
+     * @return success or not
+     *
+     */
+    public boolean
+    updateMessageOnIccEf(int index, int status, byte[] pdu) {
+        if (DBG) log("updateMessageOnIccEf: index=" + index +
+                " status=" + status + " ==> " +
+                "("+ pdu + ")");
+        enforceReceiveAndSend("Updating message on RUIM");
+        synchronized(mLock) {
+            mSuccess = false;
+            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
+
+            if (status == STATUS_ON_ICC_FREE) {
+                // Special case FREE: call deleteSmsOnRuim instead of
+                // manipulating the RUIM record
+                mPhone.mCM.deleteSmsOnRuim(index, response);
+            } else {
+                byte[] record = makeSmsRecordData(status, pdu);
+                mPhone.getIccFileHandler().updateEFLinearFixed(
+                        IccConstants.EF_SMS, index, record, null, response);
+            }
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                log("interrupted while trying to update by index");
+            }
+        }
+        return mSuccess;
+    }
+
+    /**
+     * Copy a raw SMS PDU to the RUIM.
+     *
+     * @param pdu the raw PDU to store
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
+     * @return success or not
+     *
+     */
+    public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
+        //NOTE smsc not used in RUIM
+        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
+                "pdu=("+ pdu + ")");
+        enforceReceiveAndSend("Copying message to RUIM");
+        synchronized(mLock) {
+            mSuccess = false;
+            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
+
+            mPhone.mCM.writeSmsToRuim(status, IccUtils.bytesToHexString(pdu),
+                    response);
+
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                log("interrupted while trying to update by index");
+            }
+        }
+        return mSuccess;
+    }
+
+    /**
+     * Retrieves all messages currently stored on RUIM.
+     */
+    public List<SmsRawData> getAllMessagesFromIccEf() {
+        if (DBG) log("getAllMessagesFromEF");
+
+        Context context = mPhone.getContext();
+
+        context.enforceCallingPermission(
+                "android.permission.RECEIVE_SMS",
+                "Reading messages from RUIM");
+        synchronized(mLock) {
+            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
+            mPhone.getIccFileHandler().loadEFLinearFixedAll(IccConstants.EF_SMS, response);
+
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                log("interrupted while trying to load from the RUIM");
+            }
+        }
+        return mSms;
+    }
+
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[RuimSmsInterfaceManager] " + msg);
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
new file mode 100644
index 0000000..677d609
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -0,0 +1,908 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import android.os.Parcel;
+import android.text.format.Time;
+import android.util.Config;
+import android.util.Log;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.telephony.cdma.sms.SmsEnvelope;
+import com.android.internal.telephony.cdma.sms.UserData;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Random;
+
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+import static android.telephony.SmsMessage.MessageClass;
+
+/**
+ * A Short Message Service message.
+ *
+ */
+public class SmsMessage extends SmsMessageBase {
+    static final String LOG_TAG = "CDMA";
+
+    /**
+     *  Status of a previously submitted SMS.
+     *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
+     *  Here, the error class is defined by the bits from 9-8, the status code by the bits from 7-0.
+     *  See C.S0015-B, v2.0, 4.5.21 for a detailed description of possible values.
+     */
+    private int status;
+
+    /** The next message ID for the BearerData. Shall be a random value on first use.
+     * (See C.S0015-B, v2.0, 4.3.1.5)
+     */
+    private static int nextMessageId = 0;
+
+    /** Specifies if this is the first SMS message submit */
+    private static boolean firstSMS = true;
+
+    /** Specifies if a return of an acknowledgment is requested for send SMS */
+    private static final int RETURN_NO_ACK  = 0;
+    private static final int RETURN_ACK     = 1;
+
+    private SmsEnvelope mEnvelope;
+    private BearerData mBearerData;
+
+    public static class SubmitPdu extends SubmitPduBase {
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     * Note: In CDMA the PDU is just a byte representation of the received Sms.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        SmsMessage msg = new SmsMessage();
+
+        try {
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static SmsMessage newFromCMT(String[] lines) {
+        Log.w(LOG_TAG, "newFromCMT: is not supported in CDMA mode.");
+        return null;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static SmsMessage newFromCMTI(String line) {
+        Log.w(LOG_TAG, "newFromCMTI: is not supported in CDMA mode.");
+        return null;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static SmsMessage newFromCDS(String line) {
+        Log.w(LOG_TAG, "newFromCDS: is not supported in CDMA mode.");
+        return null;
+    }
+
+    /**
+     *  Create a "raw" CDMA SmsMessage from a Parcel that was forged in ril.cpp.
+     *  Note: Only primitive fields are set.
+     */
+    public static SmsMessage newFromParcel(Parcel p) {
+        // Note: Parcel.readByte actually reads one Int and masks to byte
+        SmsMessage msg = new SmsMessage();
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        byte[] data;
+        byte count;
+        int countInt;
+        int addressDigitMode;
+
+        //currently not supported by the modem-lib: env.mMessageType
+        env.teleService = p.readInt(); //p_cur->uTeleserviceID
+
+        if (0 != p.readByte()) { //p_cur->bIsServicePresent
+            env.messageType = SmsEnvelope.MESSAGE_TYPE_BROADCAST;
+        }
+        else {
+            if (SmsEnvelope.TELESERVICE_NOT_SET == env.teleService) {
+                // assume type ACK
+                env.messageType = SmsEnvelope.MESSAGE_TYPE_ACKNOWLEDGE;
+            } else {
+                env.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
+            }
+        }
+        env.serviceCategory = p.readInt(); //p_cur->uServicecategory
+
+        // address
+        addressDigitMode = p.readInt();
+        addr.digitMode = (byte) (0xFF & addressDigitMode); //p_cur->sAddress.digit_mode
+        addr.numberMode = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_mode
+        addr.ton = p.readInt(); //p_cur->sAddress.number_type
+        addr.numberPlan = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_plan
+        count = p.readByte(); //p_cur->sAddress.number_of_digits
+        addr.numberOfDigits = count;
+        data = new byte[count];
+        //p_cur->sAddress.digits[digitCount]
+        for (int index=0; index < count; index++) {
+            data[index] = p.readByte();
+
+            // convert the value if it is 4-bit DTMF to 8 bit
+            if (addressDigitMode == CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF) {
+                data[index] = msg.convertDtmfToAscii(data[index]);
+            }
+        }
+
+        addr.origBytes = data;
+
+        // ignore subaddress
+        p.readInt(); //p_cur->sSubAddress.subaddressType
+        p.readInt(); //p_cur->sSubAddress.odd
+        count = p.readByte(); //p_cur->sSubAddress.number_of_digits
+        //p_cur->sSubAddress.digits[digitCount] :
+        for (int index=0; index < count; index++) {
+            p.readByte();
+        }
+
+        /* currently not supported by the modem-lib:
+            env.bearerReply
+            env.replySeqNo
+            env.errorClass
+            env.causeCode
+        */
+
+        // bearer data
+        countInt = p.readInt(); //p_cur->uBearerDataLen
+        if (countInt >0) {
+            data = new byte[countInt];
+             //p_cur->aBearerData[digitCount] :
+            for (int index=0; index < countInt; index++) {
+                data[index] = p.readByte();
+            }
+            env.bearerData = data;
+            // BD gets further decoded when accessed in SMSDispatcher
+        }
+
+        // link the the filled objects to the SMS
+        env.origAddress = addr;
+        msg.originatingAddress = addr;
+        msg.mEnvelope = env;
+
+        // create byte stream representation for transportation through the layers.
+        msg.createPdu();
+
+        return msg;
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by RuimSmsInterfaceManager.getAllMessagesFromIcc + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        try {
+            SmsMessage msg = new SmsMessage();
+
+            msg.indexOnIcc = index;
+
+            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
+            // or STORED_UNSENT
+            // See 3GPP2 C.S0023 3.4.27
+            if ((data[0] & 1) == 0) {
+                Log.w(LOG_TAG, "SMS parsing failed: Trying to parse a free record");
+                return null;
+            } else {
+                msg.statusOnIcc = data[0] & 0x07;
+            }
+
+            // Second byte is the MSG_LEN, length of the message
+            // See 3GPP2 C.S0023 3.4.27
+            int size = data[1];
+
+            // Note: Data may include trailing FF's.  That's OK; message
+            // should still parse correctly.
+            byte[] pdu = new byte[size];
+            System.arraycopy(data, 2, pdu, 0, size);
+            // the message has to be parsed before it can be displayed
+            // see gsm.SmsMessage
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        Log.w(LOG_TAG, "getTPLayerLengthForPDU: is not supported in CDMA mode.");
+        return 0;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress             Service Centre address.  Null means use default.
+     * @param destinationAddress    Address of the recipient.
+     * @param message               String representation of the message payload.
+     * @param statusReportRequested Indicates whether a report is requested for this message.
+     * @param headerData            Array containing the data for the User Data Header, preceded
+     *                              by the Element Identifiers.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] headerData) {
+
+        SmsMessage sms = new SmsMessage();
+        SubmitPdu ret = new SubmitPdu();
+        UserData uData = new UserData();
+        SmsHeader smsHeader;
+        byte[] data;
+
+        // Perform null parameter checks.
+        if (message == null || destinationAddress == null) {
+            return null;
+        }
+
+        // ** Set UserData + SmsHeader **
+        try {
+            // First, try encoding it as 7-bit ASCII
+            // User Data (and length)
+
+            uData.payload = message.getBytes();
+
+            if (uData.payload.length > MAX_USER_DATA_SEPTETS) {
+                // Message too long
+                return null;
+            }
+
+            // desired TP-Data-Coding-Scheme
+            uData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
+
+            // sms header
+            if(headerData != null) {
+                smsHeader = SmsHeader.parse(headerData);
+                uData.userDataHeader = smsHeader;
+            } else {
+                // no user data header available!
+            }
+
+            data  = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
+                    (headerData != null), (null == headerData));
+
+        } catch (Exception ex) {
+            Log.e(LOG_TAG, "getSubmitPdu: 7 bit ASCII encoding in cdma.SMSMesage failed: "
+                    + ex.getMessage());
+            Log.w(LOG_TAG, "getSubmitPdu: The message will be sent as UCS-2 encoded message.");
+            byte[] textPart;
+            // Encoding to the 7-bit alphabet failed. Let's see if we can
+            // send it as a UCS-2 encoded message
+
+            try {
+                textPart = message.getBytes("utf-16be");
+            } catch (UnsupportedEncodingException uex) {
+                Log.e(LOG_TAG, "Implausible UnsupportedEncodingException ", uex);
+                return null;
+            }
+
+            uData.payload = textPart;
+
+            if (uData.payload.length > MAX_USER_DATA_BYTES) {
+                // Message too long
+                return null;
+            }
+
+            // TP-Data-Coding-Scheme
+            uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+
+            // sms header
+            if(headerData != null) {
+                smsHeader = SmsHeader.parse(headerData);
+                uData.userDataHeader = smsHeader;
+            } else {
+                // no user data header available!
+            }
+
+            data = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
+                (headerData != null), (null == headerData));
+        }
+
+        if (null == data) return null;
+
+        ret.encodedMessage = data;
+        ret.encodedScAddress = null;
+        return ret;
+    }
+
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested) {
+        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the data for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, short destinationPort, byte[] data,
+            boolean statusReportRequested) {
+
+        SmsMessage sms = new SmsMessage();
+        SubmitPdu ret = new SubmitPdu();
+        UserData uData = new UserData();
+        SmsHeader smsHeader = new SmsHeader();
+
+        if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) {
+            Log.e(LOG_TAG, "SMS data message may only contain "
+                    + (MAX_USER_DATA_BYTES - 7) + " bytes");
+            return null;
+        }
+
+        byte[] destPort = new byte[4];
+        destPort[0] = (byte) ((destinationPort >> 8) & 0xFF); // MSB of destination port
+        destPort[1] = (byte) (destinationPort & 0xFF); // LSB of destination port
+        destPort[2] = 0x00; // MSB of originating port
+        destPort[3] = 0x00; // LSB of originating port
+        smsHeader.add(
+                new SmsHeader.Element(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT, destPort));
+
+        smsHeader.nbrOfHeaders = smsHeader.getElements().size();
+        uData.userDataHeader = smsHeader;
+
+        // TP-Data-Coding-Scheme
+        // No class, 8 bit data
+        uData.msgEncoding = UserData.ENCODING_OCTET;
+        uData.payload = data;
+
+        byte[] msgData = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
+                true, true);
+
+        ret.encodedMessage = msgData;
+        ret.encodedScAddress = null;
+        return ret;
+    }
+
+    static class PduParser {
+
+        PduParser() {
+        }
+
+        /**
+         * Parses an SC timestamp and returns a currentTimeMillis()-style
+         * timestamp
+         */
+        static long getSCTimestampMillis(byte[] timestamp) {
+            // TP-Service-Centre-Time-Stamp
+            int year = IccUtils.beBcdByteToInt(timestamp[0]);
+            int month = IccUtils.beBcdByteToInt(timestamp[1]);
+            int day = IccUtils.beBcdByteToInt(timestamp[2]);
+            int hour = IccUtils.beBcdByteToInt(timestamp[3]);
+            int minute = IccUtils.beBcdByteToInt(timestamp[4]);
+            int second = IccUtils.beBcdByteToInt(timestamp[5]);
+
+            Time time = new Time(Time.TIMEZONE_UTC);
+
+            // C.S0015-B v2.0, 4.5.4: range is 1996-2095
+            time.year = year >= 96 ? year + 1900 : year + 2000;
+            time.month = month - 1;
+            time.monthDay = day;
+            time.hour = hour;
+            time.minute = minute;
+            time.second = second;
+
+            return time.toMillis(true);
+        }
+
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public int getProtocolIdentifier() {
+        Log.w(LOG_TAG, "getProtocolIdentifier: is not supported in CDMA mode.");
+        // (3GPP TS 23.040): "no interworking, but SME to SME protocol":
+        return 0;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isReplace() {
+        Log.w(LOG_TAG, "isReplace: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isCphsMwiMessage() {
+        Log.w(LOG_TAG, "isCphsMwiMessage: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMWIClearMessage() {
+        if ((mBearerData != null) && (0 == mBearerData.numberOfMessages)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMWISetMessage() {
+        if ((mBearerData != null) && (mBearerData.numberOfMessages >0)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMwiDontStore() {
+        if ((mBearerData != null) && (mBearerData.numberOfMessages >0)
+                && (null == mBearerData.userData)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the status for a previously submitted message.
+     * For not interfering with status codes from GSM, this status code is
+     * shifted to the bits 31-16.
+     */
+    public int getStatus() {
+        return(status<<16);
+    }
+
+    /**
+     *  Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isStatusReportMessage() {
+        Log.w(LOG_TAG, "isStatusReportMessage: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isReplyPathPresent() {
+        Log.w(LOG_TAG, "isReplyPathPresent: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * Returns the teleservice type of the message.
+     * @return the teleservice:
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_NOT_SET},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WMT},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WEMT},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_VMN},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WAP}
+    */
+    public int getTeleService() {
+        return mEnvelope.teleService;
+    }
+
+    /**
+     * Decodes pdu to an empty SMS object.
+     * In the CDMA case the pdu is just an internal byte stream representation
+     * of the SMS Java-object.
+     * @see #createPdu()
+     */
+    private void parsePdu(byte[] pdu) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(new BufferedInputStream(bais));
+        byte length;
+        int bearerDataLength;
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+
+        try {
+            env.messageType = dis.readInt();
+            env.teleService = dis.readInt();
+            env.serviceCategory = dis.readInt();
+
+            addr.digitMode = dis.readByte();
+            addr.numberMode = dis.readByte();
+            addr.ton = dis.readByte();
+            addr.numberPlan = dis.readByte();
+
+            length = dis.readByte();
+            addr.numberOfDigits = length;
+            addr.origBytes = new byte[length];
+            dis.read(addr.origBytes, 0, length); // digits
+
+            env.bearerReply = dis.readInt();
+            // CauseCode values:
+            env.replySeqNo = dis.readByte();
+            env.errorClass = dis.readByte();
+            env.causeCode = dis.readByte();
+
+            //encoded BearerData:
+            bearerDataLength = dis.readInt();
+            env.bearerData = new byte[bearerDataLength];
+            dis.read(env.bearerData, 0, bearerDataLength);
+            dis.close();
+        } catch (Exception ex) {
+            Log.e(LOG_TAG, "createFromPdu: conversion from byte array to object failed: " + ex);
+        }
+
+        // link the filled objects to this SMS
+        originatingAddress = addr;
+        env.origAddress = addr;
+        mEnvelope = env;
+
+        parseSms();
+    }
+
+    /**
+     * Parses a SMS message from its BearerData stream. (mobile-terminated only)
+     */
+    protected void parseSms() {
+        mBearerData = BearerData.decode(mEnvelope.bearerData);
+        messageRef = mBearerData.messageId;
+
+        // TP-Message-Type-Indicator
+        // (See 3GPP2 C.S0015-B, v2, 4.5.1)
+        int messageType = mBearerData.messageType;
+
+        switch (messageType) {
+        case BearerData.MESSAGE_TYPE_USER_ACK:
+        case BearerData.MESSAGE_TYPE_READ_ACK:
+        case BearerData.MESSAGE_TYPE_DELIVER:
+            // Deliver (mobile-terminated only)
+            parseSmsDeliver();
+            break;
+        case BearerData.MESSAGE_TYPE_DELIVERY_ACK:
+            parseSmsDeliveryAck();
+            break;
+
+        default:
+            // the rest of these
+            throw new RuntimeException("Unsupported message type: " + messageType);
+        }
+    }
+
+    /**
+     * Parses a SMS-DELIVER message. (mobile-terminated only)
+     * See 3GPP2 C.S0015-B, v2, 4.4.1
+     */
+    private void parseSmsDeliver() {
+        if (originatingAddress != null) {
+            originatingAddress.address = new String(originatingAddress.origBytes);
+            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
+                    + originatingAddress.address);
+        }
+
+        if (mBearerData.timeStamp != null) {
+                scTimeMillis = PduParser.getSCTimestampMillis(mBearerData.timeStamp);
+        }
+
+        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
+
+        parseUserData(mBearerData.userData);
+    }
+
+    /**
+     * Parses a SMS-DELIVER message. (mobile-terminated only)
+     * See 3GPP2 C.S0015-B, v2, 4.4.1
+     */
+    private void parseSmsDeliveryAck() {
+        if (originatingAddress != null) {
+            originatingAddress.address = new String(originatingAddress.origBytes);
+            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
+                    + originatingAddress.address);
+        }
+
+        if (mBearerData.timeStamp != null) {
+                scTimeMillis = PduParser.getSCTimestampMillis(mBearerData.timeStamp);
+        }
+
+        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
+
+        if (mBearerData.errorClass != BearerData.ERROR_UNDEFINED) {
+            status = mBearerData.errorClass << 8;
+            status |= mBearerData.messageStatus;
+        }
+
+        parseUserData(mBearerData.userData);
+
+    }
+
+    /**
+     * Copy parsed user data out from internal datastructures.
+     */
+    private void parseUserData(UserData uData) {
+        if (uData == null) {
+            return;
+        }
+
+        userData = uData.payload;
+        userDataHeader = uData.userDataHeader;
+        messageBody = uData.payloadStr;
+
+        if (messageBody != null) {
+            if (Config.LOGV) Log.v(LOG_TAG, "SMS message body: '" + messageBody + "'");
+            parseMessageBody();
+        } else if ((userData != null) && (Config.LOGV)) {
+            Log.v(LOG_TAG, "SMS payload: '" + IccUtils.bytesToHexString(userData) + "'");
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MessageClass getMessageClass() {
+        if (BearerData.DISPLAY_MODE_IMMEDIATE == mBearerData.displayMode ) {
+            return MessageClass.CLASS_0;
+        } else {
+            return MessageClass.UNKNOWN;
+        }
+    }
+
+    /**
+     * Creates BearerData and Envelope from parameters for a Submit SMS.
+     * @return byte stream for SubmitPdu.
+     */
+    private byte[] getEnvelope(String destinationAddress, boolean statusReportRequested,
+            UserData userData, boolean hasHeaders, boolean useNewId) {
+
+        BearerData mBearerData = new BearerData();
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress mSmsAddress = new CdmaSmsAddress();
+
+        // ** set SmsAddress **
+        mSmsAddress.digitMode = CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR;
+        try {
+            mSmsAddress.origBytes = destinationAddress.getBytes("UTF-8");
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "doGetSubmitPdu: conversion of destinationAddress from string to byte[]"
+                    + " failed: " + e.getMessage());
+            return null;
+        }
+        mSmsAddress.numberOfDigits = (byte)mSmsAddress.origBytes.length;
+        mSmsAddress.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
+        // see C.S0015-B, v2.0, 3.4.3.3
+        mSmsAddress.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY;
+        mSmsAddress.ton = CdmaSmsAddress.TON_INTERNATIONAL_OR_IP;
+
+        // ** set BearerData **
+        mBearerData.userData = userData;
+        mBearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
+
+        if (useNewId) {
+            setNextMessageId();
+        }
+        mBearerData.messageId = nextMessageId;
+
+        // Set the reply options (See C.S0015-B, v2.0, 4.5.11)
+        if(statusReportRequested) {
+            mBearerData.deliveryAckReq = true;
+        } else {
+            mBearerData.deliveryAckReq = false;
+        }
+        // Currently settings applications do not support this
+        mBearerData.userAckReq = false;
+        mBearerData.readAckReq = false;
+        mBearerData.reportReq = false;
+
+        // number of messages: not needed for encoding!
+
+        // indicate whether a user data header is available
+        mBearerData.hasUserDataHeader = hasHeaders;
+
+        // ** encode BearerData **
+        byte[] encodedBearerData = null;
+        try {
+            encodedBearerData = BearerData.encode(mBearerData);
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "doGetSubmitPdu: EncodeCdmaSMS function in JNI interface failed: "
+                    + e.getMessage());
+            return null;
+        }
+
+        // ** SmsEnvelope **
+        env.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
+        env.teleService = SmsEnvelope.TELESERVICE_WMT;
+        env.destAddress = mSmsAddress;
+        env.bearerReply = RETURN_ACK;
+        env.bearerData = encodedBearerData;
+        mEnvelope = env;
+
+        // get byte array output stream from SmsAddress object and SmsEnvelope member.
+        return serialize(mSmsAddress);
+    }
+
+    /**
+     * Set the nextMessageId to a random value between 0 and 65536
+     * See C.S0015-B, v2.0, 4.3.1.5
+     */
+    private void setNextMessageId() {
+        // Message ID, modulo 65536
+        if(firstSMS) {
+            Random generator = new Random();
+            nextMessageId = generator.nextInt(65536);
+            firstSMS = false;
+        } else {
+            nextMessageId = ++nextMessageId & 0xFFFF;
+        }
+    }
+
+    /**
+     * Creates ByteArrayOutputStream from CdmaSmsAddress and SmsEnvelope objects
+     *
+     * @param address CdmaSmsAddress object
+     * @return ByteArrayOutputStream
+     */
+    private byte[] serialize(CdmaSmsAddress destAddress) {
+        SmsEnvelope env = mEnvelope;
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
+
+        try {
+            dos.writeInt(env.teleService);
+            dos.writeInt(0); //servicePresent
+            dos.writeInt(0); //serviceCategory
+            dos.write(destAddress.digitMode);
+            dos.write(destAddress.numberMode);
+            dos.write(destAddress.ton); // number_type
+            dos.write(destAddress.numberPlan);
+            dos.write(destAddress.numberOfDigits);
+            dos.write(destAddress.origBytes, 0, destAddress.origBytes.length); // digits
+            // Subaddress is not supported.
+            dos.write(0); //subaddressType
+            dos.write(0); //subaddr_odd
+            dos.write(0); //subaddr_nbr_of_digits
+            dos.write(env.bearerData.length);
+            dos.write(env.bearerData, 0, env.bearerData.length);
+            dos.close();
+            return baos.toByteArray();
+        } catch(IOException ex) {
+            Log.e(LOG_TAG, "serialize: conversion from object to data output stream failed: " + ex);
+            return null;
+        }
+    }
+
+    /**
+     * Creates byte array (pseudo pdu) from SMS object.
+     * Note: Do not call this method more than once per object!
+     */
+    private void createPdu() {
+        SmsEnvelope env = mEnvelope;
+        CdmaSmsAddress addr = env.origAddress;
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
+
+        try {
+            dos.writeInt(env.messageType);
+            dos.writeInt(env.teleService);
+            dos.writeInt(env.serviceCategory);
+
+            dos.writeByte(addr.digitMode);
+            dos.writeByte(addr.numberMode);
+            dos.writeByte(addr.ton);
+            dos.writeByte(addr.numberPlan);
+            dos.writeByte(addr.numberOfDigits);
+            dos.write(addr.origBytes, 0, addr.origBytes.length); // digits
+
+            dos.writeInt(env.bearerReply);
+            // CauseCode values:
+            dos.writeByte(env.replySeqNo);
+            dos.writeByte(env.errorClass);
+            dos.writeByte(env.causeCode);
+            //encoded BearerData:
+            dos.writeInt(env.bearerData.length);
+            dos.write(env.bearerData, 0, env.bearerData.length);
+            dos.close();
+
+            mPdu = baos.toByteArray();
+        } catch (IOException ex) {
+            Log.e(LOG_TAG, "createPdu: conversion from object to byte array failed: " + ex);
+        }
+    }
+
+    /**
+     * Converts a 4-Bit DTMF encoded symbol from the calling address number to ASCII character
+     */
+    private byte convertDtmfToAscii(byte dtmfDigit) {
+        byte asciiDigit;
+
+        switch (dtmfDigit) {
+        case  0: asciiDigit = 68; break; // 'D'
+        case  1: asciiDigit = 49; break; // '1'
+        case  2: asciiDigit = 50; break; // '2'
+        case  3: asciiDigit = 51; break; // '3'
+        case  4: asciiDigit = 52; break; // '4'
+        case  5: asciiDigit = 53; break; // '5'
+        case  6: asciiDigit = 54; break; // '6'
+        case  7: asciiDigit = 55; break; // '7'
+        case  8: asciiDigit = 56; break; // '8'
+        case  9: asciiDigit = 57; break; // '9'
+        case 10: asciiDigit = 48; break; // '0'
+        case 11: asciiDigit = 42; break; // '*'
+        case 12: asciiDigit = 35; break; // '#'
+        case 13: asciiDigit = 65; break; // 'A'
+        case 14: asciiDigit = 66; break; // 'B'
+        case 15: asciiDigit = 67; break; // 'C'
+        default:
+            asciiDigit = 32; // Invalid DTMF code
+            break;
+        }
+
+        return asciiDigit;
+    }
+
+
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
new file mode 100644
index 0000000..f27f79c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+public class TtyIntent {
+
+    private static final String TAG = "TtyIntent";
+
+
+    /** Event for TTY mode change */
+
+    /**
+     * Broadcast intent action indicating that the TTY has either been
+     * enabled or disabled. An intent extra provides this state as a boolean,
+     * where {@code true} means enabled.
+     * @see #TTY_ENABLED
+     *
+     * {@hide}
+     */
+    public static final String TTY_ENABLED_CHANGE_ACTION =
+        "com.android.internal.telephony.cdma.intent.action.TTY_ENABLED_CHANGE";
+
+    /**
+     * The lookup key for a boolean that indicates whether TTY mode is enabled or
+     * disabled. {@code true} means TTY mode is enabled. Retrieve it with
+     * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+     *
+     * {@hide}
+     */
+    public static final String TTY_ENABLED = "ttyEnabled";
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/package.html b/telephony/java/com/android/internal/telephony/cdma/package.html
new file mode 100644
index 0000000..cf1ad4a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/package.html
@@ -0,0 +1,6 @@
+<HTML>
+<BODY>
+Provides classes to control or read data from CDMA phones. 
+@hide
+</BODY>
+</HTML>
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
new file mode 100644
index 0000000..b5952a1
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -0,0 +1,846 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import android.util.Log;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.cdma.sms.UserData;
+
+import com.android.internal.util.HexDump;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+
+/**
+ * XXX
+ *
+ *
+ */
+public final class BearerData{
+    private final static String LOG_TAG = "SMS";
+
+    /**
+     * Bearer Data Subparameter Indentifiers
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1)
+     */
+    private final static byte SUBPARAM_MESSAGE_IDENTIFIER               = 0x00;
+    private final static byte SUBPARAM_USER_DATA                        = 0x01;
+    private final static byte SUBPARAM_USER_REPONSE_CODE                = 0x02;
+    private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP        = 0x03;
+    //private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE         = 0x04;
+    //private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE         = 0x05;
+    //private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE  = 0x06;
+    //private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE  = 0x07;
+    private final static byte SUBPARAM_PRIORITY_INDICATOR               = 0x08;
+    private final static byte SUBPARAM_PRIVACY_INDICATOR                = 0x09;
+    private final static byte SUBPARAM_REPLY_OPTION                     = 0x0A;
+    private final static byte SUBPARAM_NUMBER_OF_MESSAGES               = 0x0B;
+    private final static byte SUBPARAM_ALERT_ON_MESSAGE_DELIVERY        = 0x0C;
+    private final static byte SUBPARAM_LANGUAGE_INDICATOR               = 0x0D;
+    private final static byte SUBPARAM_CALLBACK_NUMBER                  = 0x0E;
+    private final static byte SUBPARAM_MESSAGE_DISPLAY_MODE             = 0x0F;
+    //private final static byte SUBPARAM_MULTIPLE_ENCODING_USER_DATA      = 0x10;
+    //private final static byte SUBPARAM_MESSAGE_DEPOSIT_INDEX            = 0x11;
+    //private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA    = 0x12;
+    //private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS = 0x13;
+    private final static byte SUBPARAM_MESSAGE_STATUS                   = 0x14;
+    //private final static byte SUBPARAM_TP_FAILURE_CAUSE                 = 0x15;
+    //private final static byte SUBPARAM_ENHANCED_VMN                     = 0x16;
+    //private final static byte SUBPARAM_ENHANCED_VMN_ACK                 = 0x17;
+
+    /**
+     * Supported message types for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1)
+     */
+    public static final int MESSAGE_TYPE_DELIVER        = 0x01;
+    public static final int MESSAGE_TYPE_SUBMIT         = 0x02;
+    public static final int MESSAGE_TYPE_CANCELLATION   = 0x03;
+    public static final int MESSAGE_TYPE_DELIVERY_ACK   = 0x04;
+    public static final int MESSAGE_TYPE_USER_ACK       = 0x05;
+    public static final int MESSAGE_TYPE_READ_ACK       = 0x06;
+    public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07;
+    public static final int MESSAGE_TYPE_SUBMIT_REPORT  = 0x08;
+
+    public byte messageType;
+
+    /**
+     * 16-bit value indicating the message ID, which increments modulo 65536.
+     * (Special rules apply for WAP-messages.)
+     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+     */
+    public int messageId;
+
+    /**
+     * Supported priority modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1)
+     */
+    public static final int PRIORITY_NORMAL        = 0x0;
+    public static final int PRIORITY_INTERACTIVE   = 0x1;
+    public static final int PRIORITY_URGENT        = 0x2;
+    public static final int PRIORITY_EMERGENCY     = 0x3;
+
+    public boolean priorityIndicatorSet = false;
+    public byte priority = PRIORITY_NORMAL;
+
+    /**
+     * Supported privacy modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.10-1)
+     */
+    public static final int PRIVACY_NOT_RESTRICTED = 0x0;
+    public static final int PRIVACY_RESTRICTED     = 0x1;
+    public static final int PRIVACY_CONFIDENTIAL   = 0x2;
+    public static final int PRIVACY_SECRET         = 0x3;
+
+    public boolean privacyIndicatorSet = false;
+    public byte privacy = PRIVACY_NOT_RESTRICTED;
+
+    /**
+     * Supported alert priority modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.13-1)
+     */
+    public static final int ALERT_DEFAULT          = 0x0;
+    public static final int ALERT_LOW_PRIO         = 0x1;
+    public static final int ALERT_MEDIUM_PRIO      = 0x2;
+    public static final int ALERT_HIGH_PRIO        = 0x3;
+
+    public boolean alertIndicatorSet = false;
+    public int alert = ALERT_DEFAULT;
+
+    /**
+     * Supported display modes for CDMA SMS messages.  Display mode is
+     * a 2-bit value used to indicate to the mobile station when to
+     * display the received message.  (See 3GPP2 C.S0015-B, v2,
+     * 4.5.16)
+     */
+    public static final int DISPLAY_MODE_IMMEDIATE      = 0x0;
+    public static final int DISPLAY_MODE_DEFAULT        = 0x1;
+    public static final int DISPLAY_MODE_USER           = 0x2;
+
+    public boolean displayModeSet = false;
+    public byte displayMode = DISPLAY_MODE_DEFAULT;
+
+    /**
+     * Language Indicator values.  NOTE: the spec (3GPP2 C.S0015-B,
+     * v2, 4.5.14) is ambiguous as to the meaning of this field, as it
+     * refers to C.R1001-D but that reference has been crossed out.
+     * It would seem reasonable to assume the values from C.R1001-F
+     * (table 9.2-1) are to be used instead.
+     */
+    public static final int LANGUAGE_UNKNOWN  = 0x00;
+    public static final int LANGUAGE_ENGLISH  = 0x01;
+    public static final int LANGUAGE_FRENCH   = 0x02;
+    public static final int LANGUAGE_SPANISH  = 0x03;
+    public static final int LANGUAGE_JAPANESE = 0x04;
+    public static final int LANGUAGE_KOREAN   = 0x05;
+    public static final int LANGUAGE_CHINESE  = 0x06;
+    public static final int LANGUAGE_HEBREW   = 0x07;
+
+    public boolean languageIndicatorSet = false;
+    public int language = LANGUAGE_UNKNOWN;
+
+    /**
+     * SMS Message Status Codes.  The first component of the Message
+     * status indicates if an error has occurred and whether the error
+     * is considered permanent or temporary.  The second component of
+     * the Message status indicates the cause of the error (if any).
+     * (See 3GPP2 C.S0015-B, v2.0, 4.5.21)
+     */
+    /* no-error codes */
+    public static final int ERROR_NONE                   = 0x00;
+    public static final int STATUS_ACCEPTED              = 0x00;
+    public static final int STATUS_DEPOSITED_TO_INTERNET = 0x01;
+    public static final int STATUS_DELIVERED             = 0x02;
+    public static final int STATUS_CANCELLED             = 0x03;
+    /* temporary-error and permanent-error codes */
+    public static final int ERROR_TEMPORARY              = 0x02;
+    public static final int STATUS_NETWORK_CONGESTION    = 0x04;
+    public static final int STATUS_NETWORK_ERROR         = 0x05;
+    public static final int STATUS_UNKNOWN_ERROR         = 0x1F;
+    /* permanent-error codes */
+    public static final int ERROR_PERMANENT              = 0x03;
+    public static final int STATUS_CANCEL_FAILED         = 0x06;
+    public static final int STATUS_BLOCKED_DESTINATION   = 0x07;
+    public static final int STATUS_TEXT_TOO_LONG         = 0x08;
+    public static final int STATUS_DUPLICATE_MESSAGE     = 0x09;
+    public static final int STATUS_INVALID_DESTINATION   = 0x0A;
+    public static final int STATUS_MESSAGE_EXPIRED       = 0x0D;
+    /* undefined-status codes */
+    public static final int ERROR_UNDEFINED              = 0xFF;
+    public static final int STATUS_UNDEFINED             = 0xFF;
+
+    public boolean messageStatusSet = false;
+    public int errorClass = ERROR_UNDEFINED;
+    public int messageStatus = STATUS_UNDEFINED;
+
+    /**
+     * 1-bit value that indicates whether a User Data Header is present.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+     */
+    public boolean hasUserDataHeader;
+
+    /**
+     * provides the information for the user data
+     * (e.g. padding bits, user data, user data header, etc)
+     * (See 3GPP2 C.S.0015-B, v2, 4.5.2)
+     */
+    public UserData userData;
+
+    //public UserResponseCode userResponseCode;
+
+    /**
+     * 6-byte-field, see 3GPP2 C.S0015-B, v2, 4.5.4
+     * year, month, day, hours, minutes, seconds;
+     */
+    public byte[] timeStamp;
+
+    //public SmsTime validityPeriodAbsolute;
+    //public SmsRelTime validityPeriodRelative;
+    //public SmsTime deferredDeliveryTimeAbsolute;
+    //public SmsRelTime deferredDeliveryTimeRelative;
+
+    /**
+     * Reply Option
+     * 1-bit values which indicate whether SMS acknowledgment is requested or not.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.11)
+     */
+    public boolean userAckReq;
+    public boolean deliveryAckReq;
+    public boolean readAckReq;
+    public boolean reportReq;
+
+    /**
+     * The number of Messages element (8-bit value) is a decimal number in the 0 to 99 range
+     * representing the number of messages stored at the Voice Mail System. This element is
+     * used by the Voice Mail Notification service.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.12)
+     */
+    public int numberOfMessages;
+
+    /**
+     * 4-bit or 8-bit value that indicates the number to be dialed in reply to a
+     * received SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.15)
+     */
+    public CdmaSmsAddress callbackNumber;
+
+    private static class CodingException extends Exception {
+        public CodingException(String s) {
+            super(s);
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("BearerData:\n");
+        builder.append("  messageType: " + messageType + "\n");
+        builder.append("  messageId: " + (int)messageId + "\n");
+        builder.append("  priority: " + (priorityIndicatorSet ? priority : "not set") + "\n");
+        builder.append("  privacy: " + (privacyIndicatorSet ? privacy : "not set") + "\n");
+        builder.append("  alert: " + (alertIndicatorSet ? alert : "not set") + "\n");
+        builder.append("  displayMode: " + (displayModeSet ? displayMode : "not set") + "\n");
+        builder.append("  language: " + (languageIndicatorSet ? language : "not set") + "\n");
+        builder.append("  errorClass: " + (messageStatusSet ? errorClass : "not set") + "\n");
+        builder.append("  messageStatus: " + (messageStatusSet ? messageStatus : "not set") + "\n");
+        builder.append("  hasUserDataHeader: " + hasUserDataHeader + "\n");
+        builder.append("  timeStamp: " + timeStamp + "\n");
+        builder.append("  userAckReq: " + userAckReq + "\n");
+        builder.append("  deliveryAckReq: " + deliveryAckReq + "\n");
+        builder.append("  readAckReq: " + readAckReq + "\n");
+        builder.append("  reportReq: " + reportReq + "\n");
+        builder.append("  numberOfMessages: " + numberOfMessages + "\n");
+        builder.append("  callbackNumber: " + callbackNumber + "\n");
+        builder.append("  userData: " + userData + "\n");
+        return builder.toString();
+    }
+
+    private static void encodeMessageId(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 3);
+        outStream.write(4, bData.messageType);
+        outStream.write(8, bData.messageId >> 8);
+        outStream.write(8, bData.messageId);
+        outStream.write(1, bData.hasUserDataHeader ? 1 : 0);
+        outStream.skip(3);
+    }
+
+    private static void encodeUserData(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits;
+        byte[] headerData = null;
+        if (bData.hasUserDataHeader) {
+            headerData = bData.userData.userDataHeader.toByteArray();
+            dataBits += headerData.length * 8;
+        }
+        int paramBits = dataBits + 13;
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            paramBits += 8;
+        }
+        int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+        int paddingBits = (paramBytes * 8) - paramBits;
+        outStream.write(8, paramBytes);
+        outStream.write(5, bData.userData.msgEncoding);
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            outStream.write(8, bData.userData.msgType);
+        }
+        outStream.write(8, bData.userData.numFields);
+        if (headerData != null) outStream.writeByteArray(headerData.length * 8, headerData);
+        outStream.writeByteArray(dataBits, bData.userData.payload);
+        if (paddingBits > 0) outStream.write(paddingBits, 0);
+    }
+
+    private static void encodeReplyOption(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(1, bData.userAckReq     ? 1 : 0);
+        outStream.write(1, bData.deliveryAckReq ? 1 : 0);
+        outStream.write(1, bData.readAckReq     ? 1 : 0);
+        outStream.write(1, bData.reportReq      ? 1 : 0);
+        outStream.write(4, 0);
+    }
+
+    private static byte[] encodeDtmfSmsAddress(String address) {
+        int digits = address.length();
+        int dataBits = digits * 4;
+        int dataBytes = (dataBits / 8);
+        dataBytes += (dataBits % 8) > 0 ? 1 : 0;
+        byte[] rawData = new byte[dataBytes];
+        for (int i = 0; i < digits; i++) {
+            char c = address.charAt(i);
+            int val = 0;
+            if ((c >= '1') && (c <= '9')) val = c - '0';
+            else if (c == '0') val = 10;
+            else if (c == '*') val = 11;
+            else if (c == '#') val = 12;
+            else return null;
+            rawData[i / 2] |= val << (4 - ((i % 2) * 4));
+        }
+        return rawData;
+    }
+
+    private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException {
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            try {
+                addr.origBytes = addr.address.getBytes("US-ASCII");
+            } catch (java.io.UnsupportedEncodingException ex) {
+                throw new CodingException("invalid SMS address, cannot convert to ASCII");
+            }
+        } else {
+            addr.origBytes = encodeDtmfSmsAddress(addr.address);
+        }
+    }
+
+    private static void encodeCallbackNumber(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException, CodingException
+    {
+        CdmaSmsAddress addr = bData.callbackNumber;
+        encodeCdmaSmsAddress(addr);
+        int paramBits = 9;
+        int dataBits = 0;
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            paramBits += 7;
+            dataBits = addr.numberOfDigits * 8;
+        } else {
+            dataBits = addr.numberOfDigits * 4;
+        }
+        paramBits += dataBits;
+        int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+        int paddingBits = (paramBytes * 8) - paramBits;
+        outStream.write(8, paramBytes);
+        outStream.write(1, addr.digitMode);
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            outStream.write(3, addr.ton);
+            outStream.write(4, addr.numberPlan);
+        }
+        outStream.write(8, addr.numberOfDigits);
+        outStream.writeByteArray(dataBits, addr.origBytes);
+        if (paddingBits > 0) outStream.write(paddingBits, 0);
+    }
+
+    private static void encodeMsgStatus(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.errorClass);
+        outStream.write(6, bData.messageStatus);
+    }
+
+    private static void encodeMsgCount(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(8, bData.numberOfMessages);
+    }
+
+    private static void encodeMsgCenterTimeStamp(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 6);
+        outStream.writeByteArray(6 * 8, bData.timeStamp);
+    }
+
+    private static void encodePrivacyIndicator(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.privacy);
+        outStream.skip(6);
+    }
+
+    private static void encodeLanguageIndicator(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(8, bData.language);
+    }
+
+    private static void encodeDisplayMode(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.displayMode);
+        outStream.skip(6);
+    }
+
+    private static void encodePriorityIndicator(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.priority);
+        outStream.skip(6);
+    }
+
+    private static void encodeMsgDeliveryAlert(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.alert);
+        outStream.skip(6);
+    }
+
+    /**
+     * Create serialized representation for BearerData object.
+     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
+     *
+     * @param bearerData an instance of BearerData.
+     *
+     * @return data byta array of raw encoded SMS bearer data.
+     */
+    public static byte[] encode(BearerData bData) {
+        try {
+            BitwiseOutputStream outStream = new BitwiseOutputStream(200);
+            outStream.write(8, SUBPARAM_MESSAGE_IDENTIFIER);
+            encodeMessageId(bData, outStream);
+            if (bData.userData != null) {
+                outStream.write(8, SUBPARAM_USER_DATA);
+                encodeUserData(bData, outStream);
+            }
+            if (bData.callbackNumber != null) {
+                outStream.write(8, SUBPARAM_CALLBACK_NUMBER);
+                encodeCallbackNumber(bData, outStream);
+            }
+            if (bData.userAckReq || bData.deliveryAckReq || bData.readAckReq || bData.reportReq) {
+                outStream.write(8, SUBPARAM_REPLY_OPTION);
+                encodeReplyOption(bData, outStream);
+            }
+            if (bData.numberOfMessages != 0) {
+                outStream.write(8, SUBPARAM_NUMBER_OF_MESSAGES);
+                encodeMsgCount(bData, outStream);
+            }
+            if (bData.timeStamp != null) {
+                outStream.write(8, SUBPARAM_MESSAGE_CENTER_TIME_STAMP);
+                encodeMsgCenterTimeStamp(bData, outStream);
+            }
+            if (bData.privacyIndicatorSet) {
+                outStream.write(8, SUBPARAM_PRIVACY_INDICATOR);
+                encodePrivacyIndicator(bData, outStream);
+            }
+            if (bData.languageIndicatorSet) {
+                outStream.write(8, SUBPARAM_LANGUAGE_INDICATOR);
+                encodeLanguageIndicator(bData, outStream);
+            }
+            if (bData.displayModeSet) {
+                outStream.write(8, SUBPARAM_MESSAGE_DISPLAY_MODE);
+                encodeDisplayMode(bData, outStream);
+            }
+            if (bData.priorityIndicatorSet) {
+                outStream.write(8, SUBPARAM_PRIORITY_INDICATOR);
+                encodePriorityIndicator(bData, outStream);
+            }
+            if (bData.alertIndicatorSet) {
+                outStream.write(8, SUBPARAM_ALERT_ON_MESSAGE_DELIVERY);
+                encodeMsgDeliveryAlert(bData, outStream);
+            }
+            if (bData.messageStatusSet) {
+                outStream.write(8, SUBPARAM_MESSAGE_STATUS);
+                encodeMsgStatus(bData, outStream);
+            }
+            return outStream.toByteArray();
+        } catch (BitwiseOutputStream.AccessException ex) {
+            Log.e(LOG_TAG, "BearerData encode failed: " + ex);
+        } catch (CodingException ex) {
+            Log.e(LOG_TAG, "BearerData encode failed: " + ex);
+        }
+        return null;
+   }
+
+    private static void decodeMessageId(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 3) {
+            throw new CodingException("MESSAGE_IDENTIFIER subparam size incorrect");
+        }
+        bData.messageType = inStream.read(4);
+        bData.messageId = inStream.read(8) << 8;
+        bData.messageId |= inStream.read(8);
+        bData.hasUserDataHeader = (inStream.read(1) == 1);
+        inStream.skip(3);
+    }
+
+    private static void decodeUserData(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException
+    {
+        byte paramBytes = inStream.read(8);
+        bData.userData = new UserData();
+        bData.userData.msgEncoding = inStream.read(5);
+        bData.userData.msgType = 0;
+        int consumedBits = 5;
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            bData.userData.msgType = inStream.read(8);
+            consumedBits += 8;
+        }
+        bData.userData.numFields = inStream.read(8);
+        consumedBits += 8;
+        int dataBits = (paramBytes * 8) - consumedBits;
+        bData.userData.payload = inStream.readByteArray(dataBits);
+    }
+
+    private static String decodePayloadStr(byte[] data, int offset, int numFields, String format)
+        throws CodingException
+    {
+        try {
+            return new String(data, offset, numFields, format);
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new CodingException("invalid ASCII user data code");
+        }
+    }
+
+    private static String decodeIa5(byte[] data, int offset, int numFields) {
+        try {
+            StringBuffer strBuf = new StringBuffer(numFields);
+            BitwiseInputStream inStream = new BitwiseInputStream(data);
+            inStream.skip(offset);
+            int wantedBits = numFields * 7;
+            if (inStream.available() < wantedBits) {
+                throw new CodingException("insufficient data (wanted " + wantedBits +
+                                          " bits, but only have " + inStream.available() + ")");
+            }
+            for (int i = 0; i < numFields; i++) {
+                int charCode = inStream.read(7);
+                if ((charCode < UserData.IA5_MAP_BASE_INDEX) ||
+                        (charCode > UserData.IA5_MAP_MAX_INDEX)) {
+                    throw new CodingException("unsupported AI5 character code (" + charCode + ")");
+                }
+                strBuf.append(UserData.IA5_MAP[charCode - UserData.IA5_MAP_BASE_INDEX]);
+            }
+            return strBuf.toString();
+        } catch (BitwiseInputStream.AccessException ex) {
+            Log.e(LOG_TAG, "UserData AI5 decode failed: " + ex);
+        } catch (CodingException ex) {
+            Log.e(LOG_TAG, "UserData AI5 decode failed: " + ex);
+        }
+        return null;
+    }
+
+    private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader)
+        throws CodingException
+    {
+        int offset = 0;
+        if (hasUserDataHeader) {
+            int UdhLen = userData.payload[0];
+            byte[] headerData = new byte[UdhLen];
+            System.arraycopy(userData.payload, 1, headerData, 0, UdhLen);
+            userData.userDataHeader = SmsHeader.parse(headerData);
+        }
+        switch (userData.msgEncoding) {
+        case UserData.ENCODING_OCTET:
+            break;
+        case UserData.ENCODING_7BIT_ASCII:
+            userData.payloadStr = decodePayloadStr(userData.payload, offset,
+                                                   userData.numFields, "US-ASCII");
+            break;
+        case UserData.ENCODING_IA5:
+            userData.payloadStr = decodeIa5(userData.payload, offset, userData.numFields);
+            break;
+        case UserData.ENCODING_UNICODE_16:
+            userData.payloadStr = decodePayloadStr(userData.payload, offset,
+                                                   userData.numFields * 2, "UTF-16");
+            break;
+        case UserData.ENCODING_GSM_7BIT_ALPHABET:
+            userData.payloadStr = GsmAlphabet.gsm7BitPackedToString(userData.payload,
+                                                                    offset, userData.numFields);
+            break;
+        default:
+            throw new CodingException("unsupported user data encoding ("
+                                      + userData.msgEncoding + ")");
+        }
+    }
+
+    private static void decodeReplyOption(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        byte paramBytes = inStream.read(8);
+        if (paramBytes != 1) {
+            throw new CodingException("REPLY_OPTION subparam size incorrect");
+        }
+        bData.userAckReq     = (inStream.read(1) == 1);
+        bData.deliveryAckReq = (inStream.read(1) == 1);
+        bData.readAckReq     = (inStream.read(1) == 1);
+        bData.reportReq      = (inStream.read(1) == 1);
+        inStream.skip(4);
+    }
+
+    private static void decodeMsgCount(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("NUMBER_OF_MESSAGES subparam size incorrect");
+        }
+        bData.numberOfMessages = inStream.read(8);
+    }
+
+    private static String decodeDtmfSmsAddress(byte[] rawData, int numFields)
+        throws CodingException
+    {
+        /* DTMF 4-bit digit encoding, defined in at
+         * 3GPP2 C.S005-D, v2.0, table 2.7.1.3.2.4-4 */
+        StringBuffer strBuf = new StringBuffer(numFields);
+        for (int i = 0; i < numFields; i++) {
+            int val = 0x0F & (rawData[i / 2] >>> (4 - ((i % 2) * 4)));
+            if ((val >= 1) && (val <= 9)) strBuf.append(Integer.toString(val, 10));
+            else if (val == 10) strBuf.append('0');
+            else if (val == 11) strBuf.append('*');
+            else if (val == 12) strBuf.append('#');
+            else throw new CodingException("invalid SMS address DTMF code (" + val + ")");
+        }
+        return strBuf.toString();
+    }
+
+    private static void decodeSmsAddress(CdmaSmsAddress addr) throws CodingException {
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            try {
+                /* As specified in 3GPP2 C.S0015-B, v2, 4.5.15 -- actually
+                 * just 7-bit ASCII encoding, with the MSB being zero. */
+                addr.address = new String(addr.origBytes, 0, addr.origBytes.length, "US-ASCII");
+            } catch (java.io.UnsupportedEncodingException ex) {
+                throw new CodingException("invalid SMS address ASCII code");
+            }
+        } else {
+            addr.address = decodeDtmfSmsAddress(addr.origBytes, addr.numberOfDigits);
+        }
+    }
+
+    private static void decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        byte paramBytes = inStream.read(8);
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.digitMode = inStream.read(1);
+        byte fieldBits = 4;
+        byte consumedBits = 1;
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            addr.ton = inStream.read(3);
+            addr.numberPlan = inStream.read(4);
+            fieldBits = 8;
+            consumedBits += 7;
+        }
+        addr.numberOfDigits = inStream.read(8);
+        consumedBits += 8;
+        int remainingBits = (paramBytes * 8) - consumedBits;
+        int dataBits = addr.numberOfDigits * fieldBits;
+        int paddingBits = remainingBits - dataBits;
+        if (remainingBits < dataBits) {
+            throw new CodingException("CALLBACK_NUMBER subparam encoding size error (" +
+                                      "remainingBits " + remainingBits + ", dataBits " +
+                                      dataBits + ", paddingBits " + paddingBits + ")");
+        }
+        addr.origBytes = inStream.readByteArray(dataBits);
+        inStream.skip(paddingBits);
+        decodeSmsAddress(addr);
+        bData.callbackNumber = addr;
+    }
+
+    private static void decodeMsgStatus(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("MESSAGE_STATUS subparam size incorrect");
+        }
+        bData.errorClass = inStream.read(2);
+        bData.messageStatus = inStream.read(6);
+        bData.messageStatusSet = true;
+    }
+
+    private static void decodeMsgCenterTimeStamp(BearerData bData,
+                                                 BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 6) {
+            throw new CodingException("MESSAGE_CENTER_TIME_STAMP subparam size incorrect");
+        }
+        bData.timeStamp = inStream.readByteArray(6 * 8);
+    }
+
+    private static void decodePrivacyIndicator(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("PRIVACY_INDICATOR subparam size incorrect");
+        }
+        bData.privacy = inStream.read(2);
+        inStream.skip(6);
+        bData.privacyIndicatorSet = true;
+    }
+
+    private static void decodeLanguageIndicator(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("LANGUAGE_INDICATOR subparam size incorrect");
+        }
+        bData.language = inStream.read(8);
+        bData.languageIndicatorSet = true;
+    }
+
+    private static void decodeDisplayMode(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("DISPLAY_MODE subparam size incorrect");
+        }
+        bData.displayMode = inStream.read(2);
+        inStream.skip(6);
+        bData.displayModeSet = true;
+    }
+
+    private static void decodePriorityIndicator(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("PRIORITY_INDICATOR subparam size incorrect");
+        }
+        bData.priority = inStream.read(2);
+        inStream.skip(6);
+        bData.priorityIndicatorSet = true;
+    }
+
+    private static void decodeMsgDeliveryAlert(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("ALERT_ON_MESSAGE_DELIVERY subparam size incorrect");
+        }
+        bData.alert = inStream.read(2);
+        inStream.skip(6);
+        bData.alertIndicatorSet = true;
+    }
+
+    /**
+     * Create BearerData object from serialized representation.
+     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
+     *
+     * @param smsData byte array of raw encoded SMS bearer data.
+     *
+     * @return an instance of BearerData.
+     */
+    public static BearerData decode(byte[] smsData) {
+        try {
+            BitwiseInputStream inStream = new BitwiseInputStream(smsData);
+            BearerData bData = new BearerData();
+            int foundSubparamMask = 0;
+            while (inStream.available() > 0) {
+                int subparamId = inStream.read(8);
+                int subparamIdBit = 1 << subparamId;
+                if ((foundSubparamMask & subparamIdBit) != 0) {
+                    throw new CodingException("illegal duplicate subparameter (" +
+                                              subparamId + ")");
+                }
+                foundSubparamMask |= subparamIdBit;
+                switch (subparamId) {
+                case SUBPARAM_MESSAGE_IDENTIFIER:
+                    decodeMessageId(bData, inStream);
+                    break;
+                case SUBPARAM_USER_DATA:
+                    decodeUserData(bData, inStream);
+                    break;
+                case SUBPARAM_REPLY_OPTION:
+                    decodeReplyOption(bData, inStream);
+                    break;
+                case SUBPARAM_NUMBER_OF_MESSAGES:
+                    decodeMsgCount(bData, inStream);
+                    break;
+                case SUBPARAM_CALLBACK_NUMBER:
+                    decodeCallbackNumber(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_STATUS:
+                    decodeMsgStatus(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
+                    decodeMsgCenterTimeStamp(bData, inStream);
+                    break;
+                case SUBPARAM_PRIVACY_INDICATOR:
+                    decodePrivacyIndicator(bData, inStream);
+                    break;
+                case SUBPARAM_LANGUAGE_INDICATOR:
+                    decodeLanguageIndicator(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_DISPLAY_MODE:
+                    decodeDisplayMode(bData, inStream);
+                    break;
+                case SUBPARAM_PRIORITY_INDICATOR:
+                    decodePriorityIndicator(bData, inStream);
+                    break;
+                case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY:
+                    decodeMsgDeliveryAlert(bData, inStream);
+                    break;
+                default:
+                    throw new CodingException("unsupported bearer data subparameter ("
+                                              + subparamId + ")");
+                }
+            }
+            if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
+                throw new CodingException("missing MESSAGE_IDENTIFIER subparam");
+            }
+            if (bData.userData != null) {
+                decodeUserDataPayload(bData.userData, bData.hasUserDataHeader);
+            }
+            return bData;
+        } catch (BitwiseInputStream.AccessException ex) {
+            Log.e(LOG_TAG, "BearerData decode failed: " + ex);
+        } catch (CodingException ex) {
+            Log.e(LOG_TAG, "BearerData decode failed: " + ex);
+        }
+        return null;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
new file mode 100644
index 0000000..440debb
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import com.android.internal.telephony.SmsAddress;
+import com.android.internal.util.HexDump;
+
+public class CdmaSmsAddress extends SmsAddress {
+    /**
+     * digit mode indicators
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int DIGIT_MODE_4BIT_DTMF              = 0x00;
+    static public final int DIGIT_MODE_8BIT_CHAR              = 0x01;
+
+    /**
+     * number mode indicators
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int NUMBER_MODE_NOT_DATA_NETWORK      = 0x00;
+    static public final int NUMBER_MODE_DATA_NETWORK          = 0x01;
+
+    /**
+     *  number types for data networks
+     *  (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int TON_UNKNOWN                   = 0x00;
+    static public final int TON_INTERNATIONAL_OR_IP       = 0x01;
+    static public final int TON_NATIONAL_OR_EMAIL         = 0x02;
+    static public final int TON_NETWORK                   = 0x03;
+    static public final int TON_SUBSCRIBER                = 0x04;
+    static public final int TON_ALPHANUMERIC              = 0x05;
+    static public final int TON_ABBREVIATED               = 0x06;
+    static public final int TON_RESERVED                  = 0x07;
+
+    /**
+     *  maximum lengths for fields as defined in ril_cdma_sms.h
+     */
+    static public final int SMS_ADDRESS_MAX          =  36;
+    static public final int SMS_SUBADDRESS_MAX       =  36;
+
+    /**
+     *  Supported numbering plan identification
+     *  (See C.S005-D, v1.0, table 2.7.1.3.2.4-3)
+     */
+    static public final int NUMBERING_PLAN_UNKNOWN           = 0x0;
+    static public final int NUMBERING_PLAN_ISDN_TELEPHONY    = 0x1;
+    //static protected final int NUMBERING_PLAN_DATA              = 0x3;
+    //static protected final int NUMBERING_PLAN_TELEX             = 0x4;
+    //static protected final int NUMBERING_PLAN_PRIVATE           = 0x9;
+
+    /**
+     * 1-bit value that indicates whether the address digits are 4-bit DTMF codes
+     * or 8-bit codes.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public byte digitMode;
+
+    /**
+     * 1-bit value that indicates whether the address type is a data network address or not.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public byte numberMode;
+
+    // use parent class member ton instead public byte numberType;
+
+    /**
+     * 0 or 4-bit value that indicates which numbering plan identification is set.
+     * (See 3GPP2, C.S0015-B, v2, 3.4.3.3 and C.S005-D, table2.7.1.3.2.4-3)
+     */
+    public byte numberPlan;
+
+    /**
+     * This field shall be set to the number of address digits
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public byte numberOfDigits;
+
+    // use parent class member orig_bytes instead of public byte[] digits;
+
+    // Constructor
+    public CdmaSmsAddress(){
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("CdmaSmsAddress:\n");
+        builder.append("  digitMode: " + digitMode + "\n");
+        builder.append("  numberMode: " + numberMode + "\n");
+        builder.append("  numberPlan: " + numberPlan + "\n");
+        builder.append("  numberOfDigits: " + numberOfDigits + "\n");
+        builder.append("  ton: " + ton + "\n");
+        builder.append("  address: " + address + "\n");
+        builder.append("  origBytes: " + HexDump.toHexString(origBytes) + "\n");
+        return builder.toString();
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
new file mode 100644
index 0000000..f80e8c0
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+
+public final class SmsEnvelope{
+    /**
+     * Message Types
+     * (See 3GPP2 C.S0015-B 3.4.1)
+     */
+    static public final int MESSAGE_TYPE_POINT_TO_POINT   = 0x00;
+    static public final int MESSAGE_TYPE_BROADCAST        = 0x01;
+    static public final int MESSAGE_TYPE_ACKNOWLEDGE      = 0x02;
+
+    /**
+     * Supported Teleservices
+     * (See 3GPP2 N.S0005 and TIA-41)
+     */
+    static public final int TELESERVICE_NOT_SET           = 0x0000;
+    static public final int TELESERVICE_WMT               = 0x1002;
+    static public final int TELESERVICE_VMN               = 0x1003;
+    static public final int TELESERVICE_WAP               = 0x1004;
+    static public final int TELESERVICE_WEMT              = 0x1005;
+
+    // ServiceCategories for Cell Broadcast, see 3GPP2 C.R1001 table 9.3.1-1
+    //static public final int SERVICECATEGORY_EMERGENCY      = 0x0010;
+    //...
+
+    /**
+     *  maximum lengths for fields as defined in ril_cdma_sms.h
+     */
+    static public final int SMS_BEARER_DATA_MAX = 255;
+
+    /**
+     * Provides the type of a SMS message like point to point, broadcast or acknowledge
+     */
+    public int messageType;
+
+    /**
+     * The 16-bit Teleservice parameter identifies which upper layer service access point is sending
+     * or receiving the message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.1)
+     */
+    public int teleService = TELESERVICE_NOT_SET;
+
+    /**
+     * The 16-bit service category parameter identifies the type of service provided
+     * by the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.2)
+     */
+    public int serviceCategory;
+
+    /**
+     * The origination address identifies the originator of the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.4)
+     */
+    public CdmaSmsAddress origAddress;
+
+    /**
+     * The destination address identifies the target of the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.4)
+     */
+    public CdmaSmsAddress destAddress;
+
+    /**
+     * The 6-bit bearer reply parameter is used to request the return of a
+     * SMS Acknowledge Message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.5)
+     */
+    public int bearerReply;
+
+    /**
+     * Cause Code values:
+     * The cause code parameters are an indication whether an SMS error has occurred and if so,
+     * whether the condition is considered temporary or permanent.
+     * ReplySeqNo 6-bit value,
+     * ErrorClass 2-bit value,
+     * CauseCode 0-bit or 8-bit value
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.6)
+     */
+    public byte replySeqNo;
+    public byte errorClass;
+    public byte causeCode;
+
+    /**
+     * encoded bearer data
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.7)
+     */
+    public byte[] bearerData;
+
+    public SmsEnvelope() {
+        // nothing to see here
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
new file mode 100644
index 0000000..f916089
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma.sms;
+
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.util.HexDump;
+
+public class UserData{
+
+    /**
+     * User data encoding types.
+     * (See 3GPP2 C.R1001-F, v1.0, table 9.1-1)
+     */
+    public static final int ENCODING_OCTET                      = 0x00;
+    public static final int ENCODING_IS91_EXTENDED_PROTOCOL     = 0x01;
+    public static final int ENCODING_7BIT_ASCII                 = 0x02;
+    public static final int ENCODING_IA5                        = 0x03;
+    public static final int ENCODING_UNICODE_16                 = 0x04;
+    //public static final int ENCODING_SHIFT_JIS                  = 0x05;
+    //public static final int ENCODING_KOREAN                     = 0x06;
+    //public static final int ENCODING_LATIN_HEBREW               = 0x07;
+    //public static final int ENCODING_LATIN                      = 0x08;
+    public static final int ENCODING_GSM_7BIT_ALPHABET          = 0x09;
+    public static final int ENCODING_GSM_DCS                    = 0x0A;
+
+    /**
+     * IA5 data encoding character mappings.
+     * (See CCITT Rec. T.50 Tables 1 and 3)
+     */
+    public static final char[] IA5_MAP = {
+        ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
+        '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+        '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+        'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~'};
+
+    /**
+     * Mapping for IA5 values less than 32 are flow control signals
+     * and not used here.
+     */
+    public static final int IA5_MAP_BASE_INDEX = 0x20;
+    public static final int IA5_MAP_MAX_INDEX = IA5_MAP_BASE_INDEX + IA5_MAP.length - 1;
+
+    /**
+     * Contains the data header of the user data
+     */
+    public SmsHeader userDataHeader;
+
+    /**
+     * Contains the data encoding type for the SMS message
+     */
+    public int msgEncoding;
+
+    // XXX needed when encoding is IS91 or DCS (not supported yet):
+    public int msgType;
+
+    /**
+     * Number of invalid bits in the last byte of data.
+     */
+    public int paddingBits;
+
+    public int numFields;
+
+    /**
+     * Contains the user data of a SMS message
+     * (See 3GPP2 C.S0015-B, v2, 4.5.2)
+     */
+    public byte[] payload;
+    public String payloadStr;
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("UserData:\n");
+        builder.append("  msgEncoding: " + msgEncoding + "\n");
+        builder.append("  msgType: " + msgType + "\n");
+        builder.append("  paddingBits: " + paddingBits + "\n");
+        builder.append("  numFields: " + (int)numFields + "\n");
+        builder.append("  userDataHeader: " + userDataHeader + "\n");
+        builder.append("  payload: '" + HexDump.toHexString(payload) + "'");
+        builder.append(", payloadStr: '" + payloadStr + "'");
+        return builder.toString();
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/package.html b/telephony/java/com/android/internal/telephony/cdma/sms/package.html
new file mode 100644
index 0000000..48e1034
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/package.html
@@ -0,0 +1,6 @@
+<HTML>
+<BODY>
+Provides CDMA-specific features for text/data/PDU SMS messages 
+@hide
+</BODY>
+</HTML>
diff --git a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.java b/telephony/java/com/android/internal/telephony/gsm/AdnRecord.java
deleted file mode 100644
index 30df699..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import com.android.internal.telephony.*;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.Message;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.AsyncResult;
-import android.util.Log;
-import android.telephony.PhoneNumberUtils;
-import java.util.ArrayList;
-
-class AdnRecordLoader extends Handler
-{
-    static final String LOG_TAG = "GSM";
-
-    //***** Instance Variables
-
-    GSMPhone phone;
-    int ef;
-    int extensionEF;
-    int pendingExtLoads;
-    Message userResponse;
-    String pin2;
-
-    // For "load one"
-    int recordNumber;
-
-    // for "load all"
-    ArrayList<AdnRecord> adns; // only valid after EVENT_ADN_LOAD_ALL_DONE
-
-    // Either an AdnRecord or a reference to adns depending
-    // if this is a load one or load all operation
-    Object result;
-
-    //***** Event Constants
-
-    static final int EVENT_ADN_LOAD_DONE = 1;
-    static final int EVENT_EXT_RECORD_LOAD_DONE = 2;
-    static final int EVENT_ADN_LOAD_ALL_DONE = 3;
-    static final int EVENT_EF_LINEAR_RECORD_SIZE_DONE = 4;
-    static final int EVENT_UPDATE_RECORD_DONE = 5;
-
-    //***** Constructor
-
-    AdnRecordLoader(GSMPhone phone)
-    {
-        // The telephony unit-test cases may create AdnRecords
-        // in secondary threads
-        super(phone.h.getLooper());
-
-        this.phone = phone;
-    }
-
-    /**
-     * Resulting AdnRecord is placed in response.obj.result
-     * or response.obj.exception is set
-     */
-    void
-    loadFromEF(int ef, int extensionEF, int recordNumber, 
-                Message response)
-    {
-        this.ef = ef;
-        this.extensionEF = extensionEF;
-        this.recordNumber = recordNumber;
-        this.userResponse = response;
-        
-        phone.mSIMFileHandler.loadEFLinearFixed(
-                    ef, recordNumber, 
-                    obtainMessage(EVENT_ADN_LOAD_DONE)); 
-
-    }
-
-
-    /**
-     * Resulting ArrayList&lt;adnRecord> is placed in response.obj.result
-     * or response.obj.exception is set
-     */
-    void
-    loadAllFromEF(int ef, int extensionEF, 
-                Message response)
-    {
-        this.ef = ef;
-        this.extensionEF = extensionEF;
-        this.userResponse = response;
-        
-        phone.mSIMFileHandler.loadEFLinearFixedAll(
-                    ef, 
-                    obtainMessage(EVENT_ADN_LOAD_ALL_DONE)); 
-
-    }
-
-    /**
-     * Write adn to a EF SIM record
-     * It will get the record size of EF record and compose hex adn array
-     * then write the hex array to EF record
-     *
-     * @param adn is set with alphaTag and phoneNubmer
-     * @param ef EF fileid
-     * @param extensionEF extension EF fileid
-     * @param recordNumber 1-based record index
-     * @param pin2 for CHV2 operations, must be null if pin2 is not needed
-     * @param response will be sent to its handler when completed
-     */
-    void
-    updateEF(AdnRecord adn, int ef, int extensionEF, int recordNumber,
-            String pin2, Message response)
-    {
-        this.ef = ef;
-        this.extensionEF = extensionEF;
-        this.recordNumber = recordNumber;
-        this.userResponse = response;
-        this.pin2 = pin2;
-
-        phone.mSIMFileHandler.getEFLinearRecordSize( ef,
-            obtainMessage(EVENT_EF_LINEAR_RECORD_SIZE_DONE, adn));
-    }
-
-    //***** Overridden from Handler
-
-    public void 
-    handleMessage(Message msg)
-    {
-        AsyncResult ar;
-        byte data[];
-        AdnRecord adn;
-
-        try {
-            switch (msg.what) {
-                case EVENT_EF_LINEAR_RECORD_SIZE_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    adn = (AdnRecord)(ar.userObj);
-
-                    if (ar.exception != null) {
-                        throw new RuntimeException("get EF record size failed",
-                                ar.exception);
-                    }
-
-                    int[] recordSize = (int[])ar.result;
-                    // recordSize is int[3] array
-                    // int[0]  is the record length
-                    // int[1]  is the total length of the EF file
-                    // int[2]  is the number of records in the EF file
-                    // So int[0] * int[2] = int[1]
-                   if (recordSize.length != 3 || recordNumber > recordSize[2]) {
-                        throw new RuntimeException("get wrong EF record size format",
-                                ar.exception);
-                    }
-
-                    data = adn.buildAdnString(recordSize[0]);
-
-                    if(data == null) {
-                        throw new RuntimeException("worong ADN format",
-                                ar.exception);
-                    }
-
-                    phone.mSIMFileHandler.updateEFLinearFixed(ef, recordNumber,
-                            data, pin2, obtainMessage(EVENT_UPDATE_RECORD_DONE));
-
-                    pendingExtLoads = 1;
-
-                    break;
-                case EVENT_UPDATE_RECORD_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    if (ar.exception != null) {
-                        throw new RuntimeException("update EF adn record failed",
-                                ar.exception);
-                    }
-                    pendingExtLoads = 0;
-                    result = null;
-                    break;
-                case EVENT_ADN_LOAD_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    data = (byte[])(ar.result);
-     
-                    if (ar.exception != null) {
-                        throw new RuntimeException("load failed", ar.exception);
-                    }
-
-                    if (false) {
-                        Log.d(LOG_TAG,"ADN EF: 0x" 
-                            + Integer.toHexString(ef)
-                            + ":" + recordNumber
-                            + "\n" + SimUtils.bytesToHexString(data));
-                    }
-                    
-                    adn = new AdnRecord(ef, recordNumber, data);
-                    result = adn;
-
-                    if (adn.hasExtendedRecord()) {
-                        // If we have a valid value in the ext record field,
-                        // we're not done yet: we need to read the corresponding
-                        // ext record and append it
-
-                        pendingExtLoads = 1;
-                        
-                        phone.mSIMFileHandler.loadEFLinearFixed(
-                            extensionEF, adn.extRecord, 
-                            obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn)); 
-                    }
-                break;
-
-                case EVENT_EXT_RECORD_LOAD_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    data = (byte[])(ar.result);
-                    adn = (AdnRecord)(ar.userObj);
-     
-                    if (ar.exception != null) {
-                        throw new RuntimeException("load failed", ar.exception);
-                    }
-
-                    Log.d(LOG_TAG,"ADN extention EF: 0x" 
-                        + Integer.toHexString(extensionEF)
-                        + ":" + adn.extRecord
-                        + "\n" + SimUtils.bytesToHexString(data));
-
-                    adn.appendExtRecord(data);
-
-                    pendingExtLoads--;
-                    // result should have been set in 
-                    // EVENT_ADN_LOAD_DONE or EVENT_ADN_LOAD_ALL_DONE
-                break;            
-
-                case EVENT_ADN_LOAD_ALL_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    ArrayList<byte[]> datas = (ArrayList<byte[]>)(ar.result);
-     
-                    if (ar.exception != null) {
-                        throw new RuntimeException("load failed", ar.exception);
-                    }
-
-                    adns = new ArrayList<AdnRecord>(datas.size());
-                    result = adns;
-                    pendingExtLoads = 0;
-
-                    for(int i = 0, s = datas.size() ; i < s ; i++) {
-                        adn = new AdnRecord(ef, 1 + i, datas.get(i));
-                        adns.add(adn);
-
-                        if (adn.hasExtendedRecord()) {
-                            // If we have a valid value in the ext record field,
-                            // we're not done yet: we need to read the corresponding
-                            // ext record and append it
-
-                            pendingExtLoads++;
-                            
-                            phone.mSIMFileHandler.loadEFLinearFixed(
-                                extensionEF, adn.extRecord, 
-                                obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn)); 
-                        }
-                    }
-                break;
-            }
-        } catch (RuntimeException exc) {            
-            if (userResponse != null) {
-                AsyncResult.forMessage(userResponse) 
-                                .exception = exc;
-                userResponse.sendToTarget();
-                // Loading is all or nothing--either every load succeeds
-                // or we fail the whole thing.
-                userResponse = null;
-            }
-            return;
-        }
-
-        if (userResponse != null && pendingExtLoads == 0) {
-            AsyncResult.forMessage(userResponse).result 
-                = result;
-
-            userResponse.sendToTarget();
-            userResponse = null;
-        }
-    }
-    
-
-}
-
-/**
- * 
- * Used to load or store ADNs (Abbreviated Dialing Numbers).
- *
- * {@hide}
- *
- */
-public class AdnRecord implements Parcelable
-{
-    static final String LOG_TAG = "GSM";
-    
-    //***** Instance Variables
-
-    String alphaTag = "";
-    String number = "";
-    int extRecord = 0xff;
-    int efid;                   // or 0 if none
-    int recordNumber;           // or 0 if none
-
-
-    //***** Constants
-
-    // In an ADN record, everything but the alpha identifier
-    // is in a footer that's 14 bytes
-    static final int FOOTER_SIZE_BYTES = 14;
-
-    // Maximum size of the un-extended number field
-    static final int MAX_NUMBER_SIZE_BYTES = 11;
-
-    static final int EXT_RECORD_LENGTH_BYTES = 13;
-    static final int EXT_RECORD_TYPE_ADDITIONAL_DATA = 2;
-    static final int EXT_RECORD_TYPE_MASK = 3;
-    static final int MAX_EXT_CALLED_PARTY_LENGTH = 0xa;
-
-    // ADN offset
-    static final int ADN_BCD_NUMBER_LENGTH = 0;
-    static final int ADN_TON_AND_NPI = 1;
-    static final int ADN_DAILING_NUMBER_START = 2;
-    static final int ADN_DAILING_NUMBER_END = 11;
-    static final int ADN_CAPABILITY_ID = 12;
-    static final int ADN_EXTENSION_ID = 13;
-
-    //***** Static Methods
-
-    public static final Parcelable.Creator<AdnRecord> CREATOR
-            = new Parcelable.Creator<AdnRecord>()
-    {
-        public AdnRecord createFromParcel(Parcel source)
-        {
-            int efid;
-            int recordNumber;
-            String alphaTag;
-            String number;
-
-            efid = source.readInt();
-            recordNumber = source.readInt();
-            alphaTag = source.readString();
-            number = source.readString();
-
-            return new AdnRecord(efid, recordNumber, alphaTag, number);
-        }
-
-        public AdnRecord[] newArray(int size)
-        {
-            return new AdnRecord[size];
-        }
-    };
-
-
-    //***** Constructor
-    public
-    AdnRecord (byte[] record)
-    {
-        this(0, 0, record);
-    }
-
-    public
-    AdnRecord (int efid, int recordNumber, byte[] record)
-    {
-        this.efid = efid;
-        this.recordNumber = recordNumber;
-        parseRecord(record);
-    }
-
-    public
-    AdnRecord (String alphaTag, String number)
-    {
-        this(0, 0, alphaTag, number);
-    }
-    
-    public
-    AdnRecord (int efid, int recordNumber, String alphaTag, String number)
-    {
-        this.efid = efid;
-        this.recordNumber = recordNumber;
-        this.alphaTag = alphaTag;
-        this.number = number;
-    }
-    
-    //***** Instance Methods
-
-    public String getAlphaTag()
-    {
-        return alphaTag;
-    }
-
-    public String getNumber()
-    {
-        return number;
-    }
-
-    public String toString()
-    {
-        return "ADN Record '" + alphaTag + "' '" + number + "'";
-    }
-
-    public boolean isEmpty()
-    {
-        return alphaTag.equals("") && number.equals("");
-    }
-
-    public boolean hasExtendedRecord()
-    {
-        return extRecord != 0 && extRecord != 0xff;
-    }
-
-    public boolean isEqual(AdnRecord adn) {
-        return ( alphaTag.equals(adn.getAlphaTag()) &&
-                number.equals(adn.getNumber()) );
-    }
-    //***** Parcelable Implementation
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public void writeToParcel(Parcel dest, int flags)
-    {
-        dest.writeInt(efid);
-        dest.writeInt(recordNumber);
-        dest.writeString(alphaTag);
-        dest.writeString(number);
-    }
-
-    /**
-     * Build adn hex byte array based on record size
-     * The format of byte array is defined in 51.011 10.5.1
-     *
-     * @param recordSize is the size X of EF record
-     * @return hex byte[recordSize] to be written to EF record
-     *          return nulll for wrong format of dialing nubmer or tag
-     */
-    public byte[] buildAdnString(int recordSize) {
-        byte[] bcdNumber;
-        byte[] byteTag;
-        byte[] adnString = null;
-        int footerOffset = recordSize - FOOTER_SIZE_BYTES;
-
-        if (number == null || number.equals("") ||
-                alphaTag == null || alphaTag.equals("")) {
-
-            Log.w(LOG_TAG, "[buildAdnString] Empty alpha tag or number");
-            adnString = new byte[recordSize];
-            for (int i = 0; i < recordSize; i++) {
-                adnString[i] = (byte) 0xFF;
-            }
-        } else if (number.length()
-                > (ADN_DAILING_NUMBER_END - ADN_DAILING_NUMBER_START + 1) * 2) {
-            Log.w(LOG_TAG,
-                    "[buildAdnString] Max length of dailing number is 20");
-        } else if (alphaTag.length() > footerOffset) {
-            Log.w(LOG_TAG,
-                    "[buildAdnString] Max length of tag is " + footerOffset);
-        } else {
-
-            adnString = new byte[recordSize];
-            for (int i = 0; i < recordSize; i++) {
-                adnString[i] = (byte) 0xFF;
-            }
-
-            bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(number);
-
-            System.arraycopy(bcdNumber, 0, adnString,
-                    footerOffset + ADN_TON_AND_NPI, bcdNumber.length);
-
-            adnString[footerOffset + ADN_BCD_NUMBER_LENGTH]
-                    = (byte) (bcdNumber.length);
-            adnString[footerOffset + ADN_CAPABILITY_ID]
-                    = (byte) 0xFF; // Capacility Id
-            adnString[footerOffset + ADN_EXTENSION_ID]
-                    = (byte) 0xFF; // Extension Record Id
-
-            byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag);
-            System.arraycopy(byteTag, 0, adnString, 0, byteTag.length);
-
-        }
-
-        return adnString;
-    }
-
-    /**
-     * See TS 51.011 10.5.10
-     */
-    public void
-    appendExtRecord (byte[] extRecord) {        
-        try {
-            if (extRecord.length != EXT_RECORD_LENGTH_BYTES) {
-                return;
-            }
-
-            if ((extRecord[0] & EXT_RECORD_TYPE_MASK)
-                    != EXT_RECORD_TYPE_ADDITIONAL_DATA
-            ) {
-                return;
-            }
-
-            if ((0xff & extRecord[1]) > MAX_EXT_CALLED_PARTY_LENGTH) {
-                // invalid or empty record
-                return;
-            }
-
-            number += PhoneNumberUtils.calledPartyBCDFragmentToString(
-                                        extRecord, 2, 0xff & extRecord[1]);
-
-            // We don't support ext record chaining.
-
-        } catch (RuntimeException ex) {
-
-
-
-            
-            Log.w(LOG_TAG, "Error parsing AdnRecord ext record", ex);
-        }
-    }
-
-    //***** Private Methods
-
-    /**
-     * alphaTag and number are set to null on invalid format
-     */
-    private void
-    parseRecord(byte[] record) {
-        try {
-            alphaTag = SimUtils.adnStringFieldToString(
-                            record, 0, record.length - FOOTER_SIZE_BYTES);
-
-            int footerOffset = record.length - FOOTER_SIZE_BYTES;
-
-            int numberLength = 0xff & record[footerOffset];
-
-            if (numberLength > MAX_NUMBER_SIZE_BYTES) {
-                // Invalid number length
-                number = "";
-                return;
-            }
-
-            // Please note 51.011 10.5.1:
-            //
-            // "If the Dialling Number/SSC String does not contain 
-            // a dialling number, e.g. a control string deactivating 
-            // a service, the TON/NPI byte shall be set to 'FF' by 
-            // the ME (see note 2)."
-
-            number = PhoneNumberUtils.calledPartyBCDToString(
-                            record, footerOffset + 1, numberLength);
-
-
-            extRecord = 0xff & record[record.length - 1];
-
-        } catch (RuntimeException ex) {
-            Log.w(LOG_TAG, "Error parsing AdnRecord", ex);
-            number = "";
-            alphaTag = "";
-        }        
-    }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/BaseCommands.java b/telephony/java/com/android/internal/telephony/gsm/BaseCommands.java
deleted file mode 100644
index 8e14b43..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/BaseCommands.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import android.content.Context;
-import android.os.RegistrantList;
-import android.os.Registrant;
-import android.os.Handler;
-import android.os.AsyncResult;
-import android.os.SystemProperties;
-import android.provider.Checkin;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * {@hide}
- */
-public abstract class BaseCommands implements CommandsInterface
-{
-    static final String LOG_TAG = "GSM";
-
-    //***** Instance Variables
-    protected Context mContext;
-    protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
-    protected Object mStateMonitor = new Object();
-
-    protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
-    protected RegistrantList mOnRegistrants = new RegistrantList();
-    protected RegistrantList mAvailRegistrants = new RegistrantList();
-    protected RegistrantList mOffOrNotAvailRegistrants = new RegistrantList();
-    protected RegistrantList mNotAvailRegistrants = new RegistrantList();
-    protected RegistrantList mSIMReadyRegistrants = new RegistrantList();
-    protected RegistrantList mSIMLockedRegistrants = new RegistrantList();
-    protected RegistrantList mCallStateRegistrants = new RegistrantList();
-    protected RegistrantList mNetworkStateRegistrants = new RegistrantList();
-    protected RegistrantList mPDPRegistrants = new RegistrantList();
-    protected Registrant mSMSRegistrant;
-    protected Registrant mNITZTimeRegistrant;
-    protected Registrant mSignalStrengthRegistrant;
-    protected Registrant mUSSDRegistrant;
-    protected Registrant mSmsOnSimRegistrant;
-    /** Registrant for handling SMS Status Reports */
-    protected Registrant mSmsStatusRegistrant;
-    /** Registrant for handling Supplementary Service Notifications */
-    protected Registrant mSsnRegistrant;
-    protected Registrant mStkSessionEndRegistrant;
-    protected Registrant mStkProCmdRegistrant;
-    protected Registrant mStkEventRegistrant;
-    protected Registrant mStkCallSetUpRegistrant;
-    /** Registrant for handling SIM SMS storage full messages */
-    protected Registrant mSimSmsFullRegistrant;
-    /** Registrant for handling SIM Refresh notifications */
-    protected Registrant mSimRefreshRegistrant;
-    /** Registrant for handling RING notifications */
-    protected Registrant mRingRegistrant;
-    /** Registrant for handling RESTRICTED STATE changed notification */
-    protected Registrant mRestrictedStateRegistrant;
-
-    public BaseCommands(Context context) {
-        mContext = context;  // May be null (if so we won't log statistics)
-    }
-
-    //***** CommandsInterface implementation
-
-    public RadioState 
-    getRadioState()
-    {
-        return mState;
-    }
-
-
-    public void 
-    registerForRadioStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mRadioStateChangedRegistrants.add(r);
-            r.notifyRegistrant();
-        }
-    }
-
-    public void 
-    registerForOn(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mOnRegistrants.add(r);
-
-            if (mState.isOn()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-    
-
-    public void 
-    registerForAvailable(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mAvailRegistrants.add(r);
-
-            if (mState.isAvailable()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForNotAvailable(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mNotAvailRegistrants.add(r);
-
-            if (!mState.isAvailable()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForOffOrNotAvailable(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mOffOrNotAvailRegistrants.add(r);
-
-            if (mState == RadioState.RADIO_OFF || !mState.isAvailable()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-
-    /** Any transition into SIM_READY */
-    public void 
-    registerForSIMReady(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mSIMReadyRegistrants.add(r);
-
-            if (mState.isSIMReady()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForSIMLockedOrAbsent(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mSIMLockedRegistrants.add(r);
-
-            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForCallStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        mCallStateRegistrants.add(r);
-    }
-
-    public void 
-    registerForNetworkStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        mNetworkStateRegistrants.add(r);
-    }
-
-    public void
-    registerForPDPStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        mPDPRegistrants.add(r);
-    }
-
-    public void 
-    setOnNewSMS(Handler h, int what, Object obj)
-    {
-        mSMSRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnSmsOnSim(Handler h, int what, Object obj)
-    {
-        mSmsOnSimRegistrant = new Registrant (h, what, obj);
-    }
-    
-    public void setOnSmsStatus(Handler h, int what, Object obj) {
-        mSmsStatusRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnSignalStrengthUpdate(Handler h, int what, Object obj)
-    {
-        mSignalStrengthRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void 
-    setOnNITZTime(Handler h, int what, Object obj)
-    {
-        mNITZTimeRegistrant = new Registrant (h, what, obj);
-    }
-  
-    public void 
-    setOnUSSD(Handler h, int what, Object obj)
-    {
-        mUSSDRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnSuppServiceNotification(Handler h, int what, Object obj)
-    {
-        mSsnRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkSessionEnd(Handler h, int what, Object obj)
-    {
-        mStkSessionEndRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkProactiveCmd(Handler h, int what, Object obj)
-    {
-        mStkProCmdRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkEvent(Handler h, int what, Object obj)
-    {
-        mStkEventRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkCallSetUp(Handler h, int what, Object obj)
-    {
-        mStkCallSetUpRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void setOnSimSmsFull(Handler h, int what, Object obj) {
-        mSimSmsFullRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void setOnSimRefresh(Handler h, int what, Object obj) {
-        mSimRefreshRegistrant = new Registrant (h, what, obj);
-    }
-    
-    public void setOnCallRing(Handler h, int what, Object obj) {
-        mRingRegistrant = new Registrant (h, what, obj);
-    }
-    
-    public void
-    setOnRestrictedStateChanged(Handler h, int what, Object obj)
-    {
-        mRestrictedStateRegistrant = new Registrant (h, what, obj);
-    }
-    
-    //***** Protected Methods
-    /**
-     * Store new RadioState and send notification based on the changes
-     *
-     * This function is called only by RIL.java when receiving unsolicited
-     * RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
-     *
-     * RadioState has 5 values : RADIO_OFF, RADIO_UNAVAILABLE, SIM_NOT_READY,
-     * SIM_LOCKED_OR_ABSENT, and SIM_READY.
-     *
-     * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
-     */
-    protected void setRadioState(RadioState newState) {
-        RadioState oldState;
-        
-        synchronized (mStateMonitor) {
-            if (Config.LOGV) {
-                Log.v(LOG_TAG, "setRadioState old: " + mState
-                    + " new " + newState);
-            }
-        
-            oldState = mState;
-            mState = newState;
-            
-            if (oldState == mState) {
-                // no state transition
-                return;
-            }
-
-            if (mContext != null &&
-                newState == RadioState.RADIO_UNAVAILABLE &&
-                oldState != RadioState.RADIO_OFF) {
-                Checkin.updateStats(mContext.getContentResolver(),
-                        Checkin.Stats.Tag.PHONE_RADIO_RESETS, 1, 0.0);
-            }
-
-            mRadioStateChangedRegistrants.notifyRegistrants();
-
-            if (mState.isAvailable() && !oldState.isAvailable()) {
-                Log.d(LOG_TAG,"Notifying: radio available");
-                mAvailRegistrants.notifyRegistrants();
-                onRadioAvailable();
-            }
-
-            if (!mState.isAvailable() && oldState.isAvailable()) {
-                Log.d(LOG_TAG,"Notifying: radio not available");
-                mNotAvailRegistrants.notifyRegistrants();
-            }
-
-            if (mState.isSIMReady() && !oldState.isSIMReady()) {
-                Log.d(LOG_TAG,"Notifying: SIM ready");
-                mSIMReadyRegistrants.notifyRegistrants();
-            }
-
-            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
-                Log.d(LOG_TAG,"Notifying: SIM locked or absent");
-                mSIMLockedRegistrants.notifyRegistrants();
-            } 
-
-            if (mState.isOn() && !oldState.isOn()) {
-                Log.d(LOG_TAG,"Notifying: Radio On");
-                mOnRegistrants.notifyRegistrants();
-            } 
-
-            if ((!mState.isOn() || !mState.isAvailable()) 
-                && !((!oldState.isOn() || !oldState.isAvailable()))
-            ) {
-                Log.d(LOG_TAG,"Notifying: radio off or not available");
-                mOffOrNotAvailRegistrants.notifyRegistrants();
-            }
-        }
-    }
-    
-    protected void
-    onRadioAvailable()
-    {
-    }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
old mode 100644
new mode 100755
index f93c724..a2d3c5e
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -16,18 +16,6 @@
 
 package com.android.internal.telephony.gsm;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_DISABLE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_ENABLE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_ERASURE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_REGISTRATION;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_ALL;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_BUSY;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_NOT_REACHABLE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_NO_REPLY;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_UNCONDITIONAL;
-import static com.android.internal.telephony.gsm.CommandsInterface.SERVICE_CLASS_VOICE;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -41,26 +29,47 @@
 import android.os.RegistrantList;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
+import android.provider.Settings;
 import android.provider.Telephony;
 import android.telephony.CellLocation;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.internal.telephony.Call;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
+
+import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.IccSmsInterfaceManager;
 import com.android.internal.telephony.MmiCode;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.PhoneSubInfo;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.gsm.SimException;
+import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.gsm.stk.StkService;
 import com.android.internal.telephony.test.SimulatedRadioControl;
+import com.android.internal.telephony.IccVmNotSupportedException;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -77,40 +86,28 @@
     // from this file will go into the radio log rather than the main
     // log.  (Use "adb logcat -b radio" to see them.)
     static final String LOG_TAG = "GSM";
-    private static final boolean LOCAL_DEBUG = false;
+    private static final boolean LOCAL_DEBUG = true;
 
-    // Key used to read and write the saved network selection value
-    public static final String NETWORK_SELECTION_KEY = "network_selection_key";
-    // Key used to read/write "disable data connection on boot" pref (used for testing)
-    public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
     // Key used to read/write current ciphering state
     public static final String CIPHERING_KEY = "ciphering_key";
-    // Key used to read/write current CLIR setting
-    public static final String CLIR_KEY = "clir_key";
     // Key used to read/write voice mail number
     public static final String VM_NUMBER = "vm_number_key";
     // Key used to read/write the SIM IMSI used for storing the voice mail
     public static final String VM_SIM_IMSI = "vm_sim_imsi_key";
-    // Key used to read/write "disable DNS server check" pref (used for testing)
-    public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
 
     //***** Instance Variables
-
-    CallTracker mCT;
-    ServiceStateTracker mSST;
-    CommandsInterface mCM;
-    SMSDispatcher mSMS;
-    DataConnectionTracker mDataConnection;
-    SIMFileHandler mSIMFileHandler;
+    GsmCallTracker mCT;
+    GsmServiceStateTracker mSST;
+    GsmSMSDispatcher mSMS;
+    GsmDataConnectionTracker mDataConnection;
     SIMRecords mSIMRecords;
-    GsmSimCard mSimCard;
+    SimCard mSimCard;
     StkService mStkService;
     MyHandler h;
     ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
     SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
     SimSmsInterfaceManager mSimSmsIntManager;
     PhoneSubInfo mSubInfo;
-    boolean mDnsCheckDisabled = false;
 
 
     Registrant mPostDialHandler;
@@ -129,44 +126,17 @@
     private String mImeiSv;
     private String mVmNumber;
 
-    //***** Event Constants
-
-    static final int EVENT_RADIO_AVAILABLE          = 1;
-    /** Supplemnetary Service Notification received. */
-    static final int EVENT_SSN                      = 2;
-    static final int EVENT_SIM_RECORDS_LOADED       = 3;
-    static final int EVENT_MMI_DONE                 = 4;
-    static final int EVENT_RADIO_ON                 = 5;
-    static final int EVENT_GET_BASEBAND_VERSION_DONE = 6;
-    static final int EVENT_USSD                     = 7;
-    static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 8;
-    static final int EVENT_GET_IMEI_DONE            = 9;
-    static final int EVENT_GET_IMEISV_DONE          = 10;
-    static final int EVENT_GET_SIM_STATUS_DONE      = 11;
-    static final int EVENT_SET_CALL_FORWARD_DONE    = 12;
-    static final int EVENT_GET_CALL_FORWARD_DONE    = 13;
-    static final int EVENT_CALL_RING                = 14;
-    // Used to intercept the carriere selection calls so that 
-    // we can save the values.
-    static final int EVENT_SET_NETWORK_MANUAL_COMPLETE = 15;
-    static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 16;
-    static final int EVENT_SET_CLIR_COMPLETE = 17;
-    static final int EVENT_REGISTERED_TO_NETWORK = 18;
-    static final int EVENT_SET_VM_NUMBER_DONE = 19;
 
     //***** Constructors
 
     public
-    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier)
-    {
+    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier) {
         this(context,ci,notifier, false);
     }
 
     public
-    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode)
-    {
+    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
         super(notifier, context, unitTestMode);
-
         h = new MyHandler();
         mCM = ci;
 
@@ -174,34 +144,31 @@
             mSimulatedRadioControl = (SimulatedRadioControl) ci;
         }
 
-        mCT = new CallTracker(this);
-        mSST = new ServiceStateTracker (this);
-        mSMS = new SMSDispatcher(this);
-        mSIMFileHandler = new SIMFileHandler(this);
+        mCM.setPhoneType(RILConstants.GSM_PHONE);
+        mCT = new GsmCallTracker(this);
+        mSST = new GsmServiceStateTracker (this);
+        mSMS = new GsmSMSDispatcher(this);
+        mIccFileHandler = new SIMFileHandler(this);
         mSIMRecords = new SIMRecords(this);
-        mDataConnection = new DataConnectionTracker (this);
-        mSimCard = new GsmSimCard(this);
+        mDataConnection = new GsmDataConnectionTracker (this);
+        mSimCard = new SimCard(this);
         if (!unitTestMode) {
             mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
             mSimSmsIntManager = new SimSmsInterfaceManager(this);
             mSubInfo = new PhoneSubInfo(this);
         }
         mStkService = StkService.getInstance(mCM, mSIMRecords, mContext,
-                mSIMFileHandler, mSimCard);
-                
+                (SIMFileHandler)mIccFileHandler, mSimCard);
+
         mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
         mSIMRecords.registerForRecordsLoaded(h, EVENT_SIM_RECORDS_LOADED, null);
-        mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, 
-                                                    null);
+        mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         mCM.registerForOn(h, EVENT_RADIO_ON, null);
         mCM.setOnUSSD(h, EVENT_USSD, null);
         mCM.setOnSuppServiceNotification(h, EVENT_SSN, null);
         mCM.setOnCallRing(h, EVENT_CALL_RING, null);
         mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
 
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
-        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
-
         if (false) {
             try {
                 //debugSocket = new LocalServerSocket("com.android.internal.telephony.debug");
@@ -221,7 +188,7 @@
                                         mCM.resetRadio(null);
                                         sock.close();
                                     } catch (IOException ex) {
-                                        Log.w(LOG_TAG, 
+                                        Log.w(LOG_TAG,
                                             "Exception accepting socket", ex);
                                     }
                                 }
@@ -235,13 +202,64 @@
                 Log.w(LOG_TAG, "Failure to open com.android.internal.telephony.debug socket", ex);
             }
         }
+
+        //Change the system setting
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.GSM_PHONE);
     }
-    
+
+    public void dispose() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+            //Unregister from all former registered events
+            mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE
+            mSIMRecords.unregisterForRecordsLoaded(h); //EVENT_SIM_RECORDS_LOADED
+            mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
+            mCM.unregisterForOn(h); //EVENT_RADIO_ON
+            mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
+            mCM.unSetOnUSSD(h);
+            mCM.unSetOnSuppServiceNotification(h);
+            mCM.unSetOnCallRing(h);
+
+            mPendingMMIs.clear();
+
+            //Force all referenced classes to unregister their former registered events
+            mStkService.dispose();
+            mCT.dispose();
+            mDataConnection.dispose();
+            mSST.dispose();
+            mIccFileHandler.dispose(); // instance of SimFileHandler
+            mSIMRecords.dispose();
+            mSimCard.dispose();
+            mSimPhoneBookIntManager.dispose();
+            mSimSmsIntManager.dispose();
+            mSubInfo.dispose();
+        }
+    }
+
+    public void removeReferences() {
+            this.mSimulatedRadioControl = null;
+            this.mStkService = null;
+            this.mSimPhoneBookIntManager = null;
+            this.mSimSmsIntManager = null;
+            this.mSMS = null;
+            this.mSubInfo = null;
+            this.mSIMRecords = null;
+            this.mIccFileHandler = null;
+            this.mSimCard = null;
+            this.mDataConnection = null;
+            this.mCT = null;
+            this.mSST = null;
+    }
+
+    protected void finalize() {
+        if(LOCAL_DEBUG) Log.d(LOG_TAG, "GSMPhone finalized");
+    }
+
+
     //***** Overridden from Phone
 
-    public ServiceState 
-    getServiceState()
-    {
+    public ServiceState
+    getServiceState() {
         return mSST.ss;
     }
 
@@ -249,15 +267,13 @@
         return mSST.cellLoc;
     }
 
-    public Phone.State 
-    getState()
-    {
+    public Phone.State
+    getState() {
         return mCT.state;
     }
 
     public String
-    getPhoneName()
-    {
+    getPhoneName() {
         return "GSM";
     }
 
@@ -270,14 +286,12 @@
     }
 
     public int
-    getSignalStrengthASU()
-    {
+    getSignalStrengthASU() {
         return mSST.rssi == 99 ? -1 : mSST.rssi;
     }
 
     public boolean
-    getMessageWaitingIndicator()
-    {
+    getMessageWaitingIndicator() {
         return mSIMRecords.getVoiceMessageWaiting();
     }
 
@@ -287,8 +301,7 @@
     }
 
     public List<? extends MmiCode>
-    getPendingMmiCodes()
-    {
+    getPendingMmiCodes() {
         return mPendingMMIs;
     }
 
@@ -303,33 +316,38 @@
             // we report data connected
 
             ret = DataState.CONNECTED;
+        } else if (mSST == null) {
+            // Radio Technology Change is ongoning, dispose() and removeReferences() have
+            // already been called
+
+            ret = DataState.DISCONNECTED;
         } else if (mSST.getCurrentGprsState()
                 != ServiceState.STATE_IN_SERVICE) {
             // If we're out of service, open TCP sockets may still work
             // but no data will flow
             ret = DataState.DISCONNECTED;
         } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
-            switch (mDataConnection.state) {
-            case FAILED:
-            case IDLE:
-                ret = DataState.DISCONNECTED;
-            break;
+            switch (mDataConnection.getState()) {
+                case FAILED:
+                case IDLE:
+                    ret = DataState.DISCONNECTED;
+                break;
 
-            case CONNECTED:
-            case DISCONNECTING:
-                if ( mCT.state != Phone.State.IDLE
-                        && !mSST.isConcurrentVoiceAndData()) {
-                    ret = DataState.SUSPENDED;
-                } else {
-                    ret = DataState.CONNECTED;
-                }
-            break;
+                case CONNECTED:
+                case DISCONNECTING:
+                    if ( mCT.state != Phone.State.IDLE
+                            && !mSST.isConcurrentVoiceAndData()) {
+                        ret = DataState.SUSPENDED;
+                    } else {
+                        ret = DataState.CONNECTED;
+                    }
+                break;
 
-            case INITING:
-            case CONNECTING:
-            case SCANNING:
-                ret = DataState.CONNECTING;
-            break;
+                case INITING:
+                case CONNECTING:
+                case SCANNING:
+                    ret = DataState.CONNECTING;
+                break;
             }
         }
 
@@ -340,19 +358,18 @@
         DataActivityState ret = DataActivityState.NONE;
 
         if (mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE) {
-            switch (mDataConnection.activity) {
+            switch (mDataConnection.getActivity()) {
+                case DATAIN:
+                    ret = DataActivityState.DATAIN;
+                break;
 
-            case DATAIN:
-                ret = DataActivityState.DATAIN;
-            break;
+                case DATAOUT:
+                    ret = DataActivityState.DATAOUT;
+                break;
 
-            case DATAOUT:
-                ret = DataActivityState.DATAOUT;
-            break;
-
-            case DATAINANDOUT:
-                ret = DataActivityState.DATAINANDOUT;
-            break;
+                case DATAINANDOUT:
+                    ret = DataActivityState.DATAINANDOUT;
+                break;
             }
         }
 
@@ -371,15 +388,13 @@
      * changes to call state (including Phone and Connection changes).
      */
     /*package*/ void
-    notifyCallStateChanged()
-    {
+    notifyCallStateChanged() {
         /* we'd love it if this was package-scoped*/
         super.notifyCallStateChangedP();
     }
 
     /*package*/ void
-    notifyNewRingingConnection(Connection c)
-    {
+    notifyNewRingingConnection(Connection c) {
         /* we'd love it if this was package-scoped*/
         super.notifyNewRingingConnectionP(c);
     }
@@ -387,28 +402,26 @@
     /**
      * Notifiy registrants of a RING event.
      */
-    void notifyIncomingRing() {    
+    void notifyIncomingRing() {
         AsyncResult ar = new AsyncResult(null, this, null);
         mIncomingRingRegistrants.notifyRegistrants(ar);
     }
-    
+
     /*package*/ void
-    notifyDisconnect(Connection cn)
-    {
+    notifyDisconnect(Connection cn) {
         mDisconnectRegistrants.notifyResult(cn);
     }
 
     void notifyUnknownConnection() {
         mUnknownConnectionRegistrants.notifyResult(this);
     }
-    
+
     void notifySuppServiceFailed(SuppService code) {
         mSuppServiceFailedRegistrants.notifyResult(code);
     }
 
     /*package*/ void
-    notifyServiceStateChanged(ServiceState ss)
-    {
+    notifyServiceStateChanged(ServiceState ss) {
         super.notifyServiceStateChangedP(ss);
     }
 
@@ -418,55 +431,38 @@
     }
 
     /*package*/ void
-    notifySignalStrength()
-    {
+    notifySignalStrength() {
         mNotifier.notifySignalStrength(this);
     }
 
     /*package*/ void
-    notifyDataConnection(String reason) {
-        mNotifier.notifyDataConnection(this, reason);
-    }
-
-    /*package*/ void
     notifyDataConnectionFailed(String reason) {
         mNotifier.notifyDataConnectionFailed(this, reason);
     }
 
     /*package*/ void
-    notifyDataActivity() {
-        mNotifier.notifyDataActivity(this);
-    }
-
-    /*package*/ void
-    updateMessageWaitingIndicator(boolean mwi)
-    {
+    updateMessageWaitingIndicator(boolean mwi) {
         // this also calls notifyMessageWaitingIndicator()
         mSIMRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
     }
 
-    /*package*/ void
-    notifyMessageWaitingIndicator()
-    {
+    public void
+    notifyMessageWaitingIndicator() {
         mNotifier.notifyMessageWaitingChanged(this);
     }
 
-    /*package*/ void
+    public void
     notifyCallForwardingIndicator() {
         mNotifier.notifyCallForwardingChanged(this);
     }
 
+    // override for allowing access from other classes of this package
     /**
-     * Set a system property, unless we're in unit test mode
+     * {@inheritDoc}
      */
-
-    /*package*/ void
-    setSystemProperty(String property, String value)
-    {
-        if(getUnitTestMode()) {
-            return;
-        }
-        SystemProperties.set(property, value);
+    public final void
+    setSystemProperty(String property, String value) {
+        super.setSystemProperty(property, value);
     }
 
     public void registerForSuppServiceNotification(
@@ -480,71 +476,57 @@
         if (mSsnRegistrants.size() == 0) mCM.setSuppServiceNotifications(false, null);
     }
 
-    public void 
-    acceptCall() throws CallStateException
-    {
+    public void
+    acceptCall() throws CallStateException {
         mCT.acceptCall();
     }
 
-    public void 
-    rejectCall() throws CallStateException
-    {
+    public void
+    rejectCall() throws CallStateException {
         mCT.rejectCall();
     }
 
     public void
-    switchHoldingAndActive() throws CallStateException
-    {
+    switchHoldingAndActive() throws CallStateException {
         mCT.switchWaitingOrHoldingAndActive();
     }
 
-
-    public boolean canConference()
-    {
+    public boolean canConference() {
         return mCT.canConference();
     }
 
-    public boolean canDial()
-    {
+    public boolean canDial() {
         return mCT.canDial();
     }
 
-    public void conference() throws CallStateException
-    {
+    public void conference() throws CallStateException {
         mCT.conference();
     }
 
-    public void clearDisconnected()
-    {
-    
+    public void clearDisconnected() {
         mCT.clearDisconnected();
     }
 
-    public boolean canTransfer()
-    {
+    public boolean canTransfer() {
         return mCT.canTransfer();
     }
 
-    public void explicitCallTransfer() throws CallStateException
-    {
+    public void explicitCallTransfer() throws CallStateException {
         mCT.explicitCallTransfer();
     }
 
-    public Call
-    getForegroundCall()
-    {
+    public GsmCall
+    getForegroundCall() {
         return mCT.foregroundCall;
     }
 
-    public Call 
-    getBackgroundCall()
-    {
+    public GsmCall
+    getBackgroundCall() {
         return mCT.backgroundCall;
     }
 
-    public Call 
-    getRingingCall()
-    {
+    public GsmCall
+    getRingingCall() {
         return mCT.ringingCall;
     }
 
@@ -554,7 +536,7 @@
             return false;
         }
 
-        if (getRingingCall().getState() != Call.State.IDLE) {
+        if (getRingingCall().getState() != GsmCall.State.IDLE) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 0: rejectCall");
             try {
                 mCT.rejectCall();
@@ -563,7 +545,7 @@
                     "reject failed", e);
                 notifySuppServiceFailed(Phone.SuppService.REJECT);
             }
-        } else if (getBackgroundCall().getState() != Call.State.IDLE) {
+        } else if (getBackgroundCall().getState() != GsmCall.State.IDLE) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG,
                     "MmiCode 0: hangupWaitingOrBackground");
             mCT.hangupWaitingOrBackground();
@@ -580,21 +562,21 @@
             return false;
         }
 
-        GSMCall call = (GSMCall) getForegroundCall();
+        GsmCall call = (GsmCall) getForegroundCall();
 
         try {
             if (len > 1) {
                 char ch = dialString.charAt(1);
                 int callIndex = ch - '0';
 
-                if (callIndex >= 1 && callIndex <= CallTracker.MAX_CONNECTIONS) {
+                if (callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG,
                             "MmiCode 1: hangupConnectionByIndex " +
                             callIndex);
                     mCT.hangupConnectionByIndex(call, callIndex);
                 }
             } else {
-                if (call.getState() != Call.State.IDLE) {
+                if (call.getState() != GsmCall.State.IDLE) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG,
                             "MmiCode 1: hangup foreground");
                     //mCT.hangupForegroundResumeBackground();
@@ -622,16 +604,16 @@
             return false;
         }
 
-        GSMCall call = (GSMCall) getForegroundCall();
+        GsmCall call = (GsmCall) getForegroundCall();
 
         if (len > 1) {
             try {
                 char ch = dialString.charAt(1);
                 int callIndex = ch - '0';
-                GSMConnection conn = mCT.getConnectionByIndex(call, callIndex);
-                
+                GsmConnection conn = mCT.getConnectionByIndex(call, callIndex);
+
                 // gsm index starts at 1, up to 5 connections in a call,
-                if (conn != null && callIndex >= 1 && callIndex <= CallTracker.MAX_CONNECTIONS) {
+                if (conn != null && callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 2: separate call "+
                             callIndex);
                     mCT.separate(conn);
@@ -647,7 +629,7 @@
             }
         } else {
             try {
-                if (getRingingCall().getState() != Call.State.IDLE) {
+                if (getRingingCall().getState() != GsmCall.State.IDLE) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG,
                     "MmiCode 2: accept ringing call");
                     mCT.acceptCall();
@@ -756,9 +738,9 @@
     }
 
     boolean isInCall() {
-        Call.State foregroundCallState = getForegroundCall().getState();
-        Call.State backgroundCallState = getBackgroundCall().getState();
-        Call.State ringingCallState = getRingingCall().getState();
+        GsmCall.State foregroundCallState = getForegroundCall().getState();
+        GsmCall.State backgroundCallState = getBackgroundCall().getState();
+        GsmCall.State ringingCallState = getRingingCall().getState();
 
        return (foregroundCallState.isAlive() ||
                 backgroundCallState.isAlive() ||
@@ -797,15 +779,15 @@
 
     public boolean handlePinMmi(String dialString) {
         GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this);
-        
+
         if (mmi != null && mmi.isPinCommand()) {
             mPendingMMIs.add(mmi);
             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
             mmi.processCode();
             return true;
         }
-        
-        return false;        
+
+        return false;
     }
 
     public void sendUssdResponse(String ussdMessge) {
@@ -814,11 +796,11 @@
         mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
         mmi.sendUssd(ussdMessge);
     }
-    
+
     public void
     sendDtmf(char c) {
         if (!PhoneNumberUtils.is12Key(c)) {
-            Log.e(LOG_TAG, 
+            Log.e(LOG_TAG,
                     "sendDtmf called with invalid character '" + c + "'");
         } else {
             if (mCT.state ==  Phone.State.OFFHOOK) {
@@ -887,7 +869,7 @@
                 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
         }
 
-        return ret;        
+        return ret;
     }
 
     public String getDeviceId() {
@@ -898,11 +880,21 @@
         return mImeiSv;
     }
 
+    public String getEsn() {
+        Log.e(LOG_TAG, "[GSMPhone] getEsn() is a CDMA method");
+        return "0";
+    }
+
+    public String getMeid() {
+        Log.e(LOG_TAG, "[GSMPhone] getMeid() is a CDMA method");
+        return "0";
+    }
+
     public String getSubscriberId() {
         return mSIMRecords.imsi;
     }
 
-    public String getSimSerialNumber() {
+    public String getIccSerialNumber() {
         return mSIMRecords.iccid;
     }
 
@@ -939,37 +931,35 @@
     
     private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
         switch (commandInterfaceCFReason) {
-            case CF_REASON_UNCONDITIONAL:
-            case CF_REASON_BUSY:
-            case CF_REASON_NO_REPLY:
-            case CF_REASON_NOT_REACHABLE:
-            case CF_REASON_ALL:
-            case CF_REASON_ALL_CONDITIONAL:
-                return true;
-            default:
-                return false;
+        case CF_REASON_UNCONDITIONAL:
+        case CF_REASON_BUSY:
+        case CF_REASON_NO_REPLY:
+        case CF_REASON_NOT_REACHABLE:
+        case CF_REASON_ALL:
+        case CF_REASON_ALL_CONDITIONAL:
+            return true;
+        default:
+            return false;
         }
     }
 
     private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) {
         switch (commandInterfaceCFAction) {
-            case CF_ACTION_DISABLE:
-            case CF_ACTION_ENABLE:
-            case CF_ACTION_REGISTRATION:
-            case CF_ACTION_ERASURE:
-                return true;
-            default:
-                return false;
+        case CF_ACTION_DISABLE:
+        case CF_ACTION_ENABLE:
+        case CF_ACTION_REGISTRATION:
+        case CF_ACTION_ERASURE:
+            return true;
+        default:
+            return false;
         }
     }
-    
-    private boolean isCfEnable(int action) {
+
+    protected  boolean isCfEnable(int action) {
         return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION);
     }
-    
-    public void getCallForwardingOption(int commandInterfaceCFReason,
-                                        Message onComplete) {
-        
+
+    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
         if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "requesting call forwarding query.");
             Message resp;
@@ -983,14 +973,13 @@
     }
 
     public void setCallForwardingOption(int commandInterfaceCFAction,
-                                        int commandInterfaceCFReason,
-                                        String dialingNumber,
-                                        int timerSeconds,
-                                        Message onComplete) {
-            
-        if ((isValidCommandInterfaceCFAction(commandInterfaceCFAction)) && 
-            (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
-            
+            int commandInterfaceCFReason,
+            String dialingNumber,
+            int timerSeconds,
+            Message onComplete) {
+        if (    (isValidCommandInterfaceCFAction(commandInterfaceCFAction)) &&
+                (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
+
             Message resp;
             if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
                 resp = h.obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
@@ -1006,12 +995,12 @@
                     resp);
         }
     }
-    
+
     public void getOutgoingCallerIdDisplay(Message onComplete) {
         mCM.getCLIR(onComplete);
     }
-    
-    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, 
+
+    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
                                            Message onComplete) {
         mCM.setCLIR(commandInterfaceCLIRMode,
                 h.obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
@@ -1020,162 +1009,111 @@
     public void getCallWaiting(Message onComplete) {
         mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
     }
-    
+
     public void setCallWaiting(boolean enable, Message onComplete) {
         mCM.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
     }
-    
+
     public boolean
-    getSimRecordsLoaded() {
+    getIccRecordsLoaded() {
         return mSIMRecords.getRecordsLoaded();
     }
 
-    public SimCard
-    getSimCard() {
+    public IccCard getIccCard() {
         return mSimCard;
     }
 
-    public void 
+    public void
     getAvailableNetworks(Message response) {
         mCM.getAvailableNetworks(response);
     }
 
     /**
-     * Small container class used to hold information relevant to 
+     * Small container class used to hold information relevant to
      * the carrier selection process. operatorNumeric can be ""
-     * if we are looking for automatic selection. 
+     * if we are looking for automatic selection.
      */
     private static class NetworkSelectMessage {
         public Message message;
         public String operatorNumeric;
     }
-    
-    public void 
+
+    public void
     setNetworkSelectionModeAutomatic(Message response) {
         // wrap the response message in our own message along with
-        // an empty string (to indicate automatic selection) for the 
+        // an empty string (to indicate automatic selection) for the
         // operator's id.
         NetworkSelectMessage nsm = new NetworkSelectMessage();
         nsm.message = response;
         nsm.operatorNumeric = "";
-        
+
         // get the message
         Message msg = h.obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
-        if (LOCAL_DEBUG) 
+        if (LOCAL_DEBUG)
             Log.d(LOG_TAG, "wrapping and sending message to connect automatically");
 
         mCM.setNetworkSelectionModeAutomatic(msg);
     }
 
-    public void 
+    public void
     selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network,
-                          Message response) {
+            Message response) {
         // wrap the response message in our own message along with
         // the operator's id.
         NetworkSelectMessage nsm = new NetworkSelectMessage();
         nsm.message = response;
         nsm.operatorNumeric = network.operatorNumeric;
-        
+
         // get the message
         Message msg = h.obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
 
         mCM.setNetworkSelectionModeManual(network.operatorNumeric, msg);
     }
-    
-    /**
-     * Method to retrieve the saved operator id from the Shared Preferences
-     */
-    private String getSavedNetworkSelection() {
-        // open the shared preferences and search with our key. 
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
-        return sp.getString(NETWORK_SELECTION_KEY, "");
-    }
-
-    /**
-     * Method to restore the previously saved operator id, or reset to
-     * automatic selection, all depending upon the value in the shared
-     * preferences.
-     */
-    void restoreSavedNetworkSelection(Message response) {
-        // retrieve the operator id
-        String networkSelection = getSavedNetworkSelection();
-        
-        // set to auto if the id is empty, otherwise select the network.
-        if (TextUtils.isEmpty(networkSelection)) {
-            mCM.setNetworkSelectionModeAutomatic(response);
-        } else {
-            mCM.setNetworkSelectionModeManual(networkSelection, response);
-        }
-    }
-    
-    public void 
-    setPreferredNetworkType(int networkType, Message response) {
-        mCM.setPreferredNetworkType(networkType, response);
-    }
-
-    public void
-    getPreferredNetworkType(Message response) {
-        mCM.getPreferredNetworkType(response);
-    }
 
     public void
     getNeighboringCids(Message response) {
         mCM.getNeighboringCids(response);
     }
-    
-    public void setOnPostDialCharacter(Handler h, int what, Object obj)
-    {
+
+    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
         mPostDialHandler = new Registrant(h, what, obj);
     }
 
-
-    public void setMute(boolean muted)
-    {
+    public void setMute(boolean muted) {
         mCT.setMute(muted);
     }
-    
-    public boolean getMute()
-    {
+
+    public boolean getMute() {
         return mCT.getMute();
     }
 
-
-    public void invokeOemRilRequestRaw(byte[] data, Message response)
-    {
-        mCM.invokeOemRilRequestRaw(data, response);
-    }
-
-    public void invokeOemRilRequestStrings(String[] strings, Message response)
-    {
-        mCM.invokeOemRilRequestStrings(strings, response);
-    }
-
+    /**
+     * @deprecated
+     */
     public void getPdpContextList(Message response) {
-        mCM.getPDPContextList(response);
+        getDataCallList(response);
     }
 
-    public List<PdpConnection> getCurrentPdpList () {
-        return mDataConnection.getAllPdps();
+    public void getDataCallList(Message response) {
+        mCM.getDataCallList(response);
     }
 
     /**
-     * Disables the DNS check (i.e., allows "0.0.0.0").
-     * Useful for lab testing environment.
-     * @param b true disables the check, false enables.
+     * @deprecated
      */
-    public void disableDnsCheck(boolean b) {
-        mDnsCheckDisabled = b;
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
-        SharedPreferences.Editor editor = sp.edit();
-        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);        
-        editor.commit();
+    public List<PdpConnection> getCurrentPdpList() {
+        ArrayList<DataConnection> connections = new ArrayList<DataConnection>();
+        ArrayList<PdpConnection> pdp_list = new ArrayList<PdpConnection>();
+
+        for(int n = 0; n < connections.size(); n++) {
+            pdp_list.add((PdpConnection) connections.get(n));
+        }
+
+        return pdp_list;
     }
 
-    /**
-     * Returns true if the DNS check is currently disabled.
-     */
-    public boolean isDnsCheckDisabled() {
-        return mDnsCheckDisabled;
+    public List<DataConnection> getCurrentDataConnectionList () {
+        return mDataConnection.getAllDataConnections();
     }
 
     public void updateServiceLocation(Message response) {
@@ -1190,14 +1128,6 @@
         mSST.disableLocationUpdates();
     }
 
-    public void setBandMode(int bandMode, Message response) {
-        mCM.setBandMode(bandMode, response);
-    }
-
-    public void queryAvailableBandMode(Message response) {
-        mCM.queryAvailableBandMode(response);
-    }
-
     public boolean getDataRoamingEnabled() {
         return mDataConnection.getDataOnRoamingEnabled();
     }
@@ -1254,7 +1184,7 @@
         // check for "default"?
         boolean noData = mDataConnection.getDataEnabled() &&
             getDataConnectionState() == DataState.DISCONNECTED;
-        return !noData && getSimCard().getState() == SimCard.State.READY &&
+        return !noData && getIccCard().getState() == SimCard.State.READY &&
                 getServiceState().getState() == ServiceState.STATE_IN_SERVICE &&
             (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming());
     }
@@ -1265,9 +1195,8 @@
      * @param mmi MMI that is done
      */
     /*package*/ void
-    onMMIDone(GsmMmiCode mmi)
-    {
-        /* Only notify complete if it's on the pending list. 
+    onMMIDone(GsmMmiCode mmi) {
+        /* Only notify complete if it's on the pending list.
          * Otherwise, it's already been handled (eg, previously canceled).
          * The exception is cancellation of an incoming USSD-REQUEST, which is
          * not on the list.
@@ -1279,9 +1208,8 @@
     }
 
 
-    private void 
-    onNetworkInitiatedUssd(GsmMmiCode mmi)
-    {
+    private void
+    onNetworkInitiatedUssd(GsmMmiCode mmi) {
         mMmiCompleteRegistrants.notifyRegistrants(
             new AsyncResult(null, mmi, null));
     }
@@ -1289,18 +1217,17 @@
 
     /** ussdMode is one of CommandsInterface.USSD_MODE_* */
     private void
-    onIncomingUSSD (int ussdMode, String ussdMessage)
-    {
+    onIncomingUSSD (int ussdMode, String ussdMessage) {
         boolean isUssdError;
         boolean isUssdRequest;
-        
-        isUssdRequest 
+
+        isUssdRequest
             = (ussdMode == CommandsInterface.USSD_MODE_REQUEST);
 
-        isUssdError 
+        isUssdError
             = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY
                 && ussdMode != CommandsInterface.USSD_MODE_REQUEST);
-    
+
         // See comments in GsmMmiCode.java
         // USSD requests aren't finished until one
         // of these two events happen
@@ -1327,7 +1254,7 @@
             // also, discard if there is no message to present
             if (!isUssdError && ussdMessage != null) {
                 GsmMmiCode mmi;
-                mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage, 
+                mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
                                                    isUssdRequest,
                                                    GSMPhone.this);
                 onNetworkInitiatedUssd(mmi);
@@ -1338,7 +1265,7 @@
     /**
      * Make sure the network knows our preferred setting.
      */
-    private void syncClirSetting() {
+    protected  void syncClirSetting() {
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         int clirSetting = sp.getInt(CLIR_KEY, -1);
         if (clirSetting >= 0) {
@@ -1348,20 +1275,16 @@
 
     //***** Inner Classes
 
-    class MyHandler extends Handler
-    {
-        MyHandler()
-        {
+    class MyHandler extends Handler {
+        MyHandler() {
         }
 
-        MyHandler(Looper l)
-        {
+        MyHandler(Looper l) {
             super(l);
         }
 
         public void
-        handleMessage (Message msg) 
-        {
+        handleMessage (Message msg) {
             AsyncResult ar;
             Message onComplete;
 
@@ -1422,11 +1345,10 @@
                     if (ar.exception != null) {
                         break;
                     }
-                    
+
                     mImeiSv = (String)ar.result;
                 break;
 
-
                 case EVENT_USSD:
                     ar = (AsyncResult)msg.obj;
 
@@ -1441,7 +1363,7 @@
                     }
                 break;
 
-                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:                
+                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                     // Some MMI requests (eg USSD) are not completed
                     // within the course of a CommandsInterface request
                     // If the radio shuts off or resets while one of these
@@ -1450,10 +1372,10 @@
                     for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
                         if (mPendingMMIs.get(i).isPendingUSSD()) {
                             mPendingMMIs.get(i).onUssdFinishedError();
-                        }                            
+                        }
                     }
                 break;
-                
+
                 case EVENT_SSN:
                     ar = (AsyncResult)msg.obj;
                     SuppServiceNotification not = (SuppServiceNotification) ar.result;
@@ -1474,7 +1396,7 @@
                     
                 case EVENT_SET_VM_NUMBER_DONE:
                     ar = (AsyncResult)msg.obj;
-                    if (SimVmNotSupportedException.class.isInstance(ar.exception)) {
+                    if (IccVmNotSupportedException.class.isInstance(ar.exception)) {
                         storeVoiceMailNumber(mVmNumber);
                         ar.exception = null;
                     }
@@ -1497,15 +1419,15 @@
                         onComplete.sendToTarget();
                     }
                     break;
-                    
+
                 case EVENT_CALL_RING:
                     ar = (AsyncResult)msg.obj;
                     if (ar.exception == null) {
                         notifyIncomingRing();
                     }
                     break;
-                    
-                // handle the select network completion callbacks.    
+
+                // handle the select network completion callbacks.
                 case EVENT_SET_NETWORK_MANUAL_COMPLETE:
                 case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
                     handleSetSelectNetwork((AsyncResult) msg.obj);
@@ -1550,29 +1472,29 @@
      * Used to track the settings upon completion of the network change.
      */
     private void handleSetSelectNetwork(AsyncResult ar) {
-        // look for our wrapper within the asyncresult, skip the rest if it 
-        // is null. 
+        // look for our wrapper within the asyncresult, skip the rest if it
+        // is null.
         if (!(ar.userObj instanceof NetworkSelectMessage)) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "unexpected result from user object.");
             return;
         }
-        
+
         NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
-        
+
         // found the object, now we send off the message we had originally
-        // attached to the request. 
+        // attached to the request.
         if (nsm.message != null) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "sending original message to recipient");
             AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
             nsm.message.sendToTarget();
         }
-        
+
         // open the shared preferences editor, and write the value.
         // nsm.operatorNumeric is "" if we're in automatic.selection.
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor editor = sp.edit();
         editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric);
-        
+
         // commit and log the result.
         if (! editor.commit()) {
             Log.e(LOG_TAG, "failed to commit network selection preference");
@@ -1584,17 +1506,16 @@
      * Saves CLIR setting so that we can re-apply it as necessary
      * (in case the RIL resets it across reboots).
      */
-    /* package */ void saveClirSetting(int commandInterfaceCLIRMode) {
+    public void saveClirSetting(int commandInterfaceCLIRMode) {
         // open the shared preferences editor, and write the value.
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor editor = sp.edit();
         editor.putInt(CLIR_KEY, commandInterfaceCLIRMode);
-        
+
         // commit and log the result.
         if (! editor.commit()) {
             Log.e(LOG_TAG, "failed to commit CLIR preference");
         }
-
     }
 
     private void handleCfuQueryResult(CallForwardInfo[] infos) {
@@ -1618,7 +1539,7 @@
      * simulates various data connection states. This messes with
      * DataConnectionTracker's internal states, but doesn't actually change
      * the underlying radio connection states.
-     * 
+     *
      * @param state Phone.DataState enum.
      */
     public void simulateDataConnection(Phone.DataState state) {
@@ -1642,4 +1563,52 @@
         mDataConnection.setState(dcState);
         notifyDataConnection(null);
     }
+
+    /**
+     * Retrieves the PhoneSubInfo of the GSMPhone
+     */
+    public PhoneSubInfo getPhoneSubInfo(){
+        return mSubInfo;
+    }
+
+    /**
+     * Retrieves the IccSmsInterfaceManager of the GSMPhone
+     */
+    public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+        return mSimSmsIntManager;
+    }
+
+    /**
+     * Retrieves the IccPhoneBookInterfaceManager of the GSMPhone
+     */
+    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+        return mSimPhoneBookIntManager;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Handler getHandler(){
+        return h;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public IccFileHandler getIccFileHandler(){
+        return this.mIccFileHandler;
+    }
+
+    public void activateCellBroadcastSms(int activate, Message response) {
+        Log.e(LOG_TAG, "Error! This functionality is not implemented for GSM.");
+    }
+
+    public void getCellBroadcastSmsConfig(Message response) {
+        Log.e(LOG_TAG, "Error! This functionality is not implemented for GSM.");
+    }
+
+    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
+        Log.e(LOG_TAG, "Error! This functionality is not implemented for GSM.");
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java b/telephony/java/com/android/internal/telephony/gsm/GsmCall.java
similarity index 75%
rename from telephony/java/com/android/internal/telephony/gsm/GSMCall.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmCall.java
index 4feaf21..a92e52d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmCall.java
@@ -15,26 +15,30 @@
  */
 
 package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.Phone;
+
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * {@hide}
  */
-class GSMCall extends Call
-{
+class GsmCall extends Call {
     /*************************** Instance Variables **************************/
 
     /*package*/ ArrayList<Connection> connections = new ArrayList<Connection>();
-    /*package*/ State state = State.IDLE;
-    /*package*/ CallTracker owner;
+    /*package*/ GsmCallTracker owner;
+
 
     /***************************** Class Methods *****************************/
 
     static State
-    stateFromDCState (DriverCall.State dcState)
-    {
+    stateFromDCState (DriverCall.State dcState) {
         switch (dcState) {
             case ACTIVE:        return State.ACTIVE;
             case HOLDING:       return State.HOLDING;
@@ -45,40 +49,33 @@
             default:            throw new RuntimeException ("illegal call state:" + dcState);
         }
     }
-    
+
 
     /****************************** Constructors *****************************/
     /*package*/
-    GSMCall (CallTracker owner)
-    {
+    GsmCall (GsmCallTracker owner) {
         this.owner = owner;
     }
 
+    public void dispose() {
+    }
+
     /************************** Overridden from Call *************************/
 
     public List<Connection>
-    getConnections()
-    {
+    getConnections() {
         // FIXME should return Collections.unmodifiableList();
         return connections;
     }
 
-    public State 
-    getState()
-    {
-        return state;
-    }
-
-    public Phone 
-    getPhone()
-    {
+    public Phone
+    getPhone() {
         //TODO
         return null;
     }
 
     public boolean
-    isMultiparty()
-    {
+    isMultiparty() {
         return connections.size() > 1;
     }
 
@@ -86,66 +83,60 @@
      *  background call exists, the background call will be resumed
      *  because an AT+CHLD=1 will be sent
      */
-    public void 
-    hangup() throws CallStateException
-    {
+    public void
+    hangup() throws CallStateException {
         owner.hangup(this);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return state.toString();
     }
 
-    //***** Called from GSMConnection
+    //***** Called from GsmConnection
 
     /*package*/ void
-    attach(GSMConnection conn, DriverCall dc)
-    {
+    attach(Connection conn, DriverCall dc) {
         connections.add(conn);
 
         state = stateFromDCState (dc.state);
     }
 
     /*package*/ void
-    attachFake(GSMConnection conn, State state)
-    {
+    attachFake(Connection conn, State state) {
         connections.add(conn);
 
         this.state = state;
     }
 
     /**
-     * Called by GSMConnection when it has disconnected
+     * Called by GsmConnection when it has disconnected
      */
     void
-    connectionDisconnected(GSMConnection conn)
-    {
+    connectionDisconnected(GsmConnection conn) {
         if (state != State.DISCONNECTED) {
             /* If only disconnected connections remain, we are disconnected*/
 
             boolean hasOnlyDisconnectedConnections = true;
-            
+
             for (int i = 0, s = connections.size()  ; i < s; i ++) {
-                if (connections.get(i).getState() 
+                if (connections.get(i).getState()
                     != State.DISCONNECTED
                 ) {
                     hasOnlyDisconnectedConnections = false;
                     break;
-                }            
+                }
             }
 
             if (hasOnlyDisconnectedConnections) {
-                state = State.DISCONNECTED;            
+                state = State.DISCONNECTED;
             }
-        }    
+        }
     }
 
 
     /*package*/ void
-    detach(GSMConnection conn)
-    {
+    detach(GsmConnection conn) {
         connections.remove(conn);
 
         if (connections.size() == 0) {
@@ -154,13 +145,12 @@
     }
 
     /*package*/ boolean
-    update (GSMConnection conn, DriverCall dc)
-    {
+    update (GsmConnection conn, DriverCall dc) {
         State newState;
         boolean changed = false;
-        
+
         newState = stateFromDCState(dc.state);
-        
+
         if (newState != state) {
             state = newState;
             changed = true;
@@ -174,44 +164,41 @@
      * connections to be added via "conference"
      */
     /*package*/ boolean
-    isFull()
-    {
-        return connections.size() == CallTracker.MAX_CONNECTIONS_PER_CALL;
+    isFull() {
+        return connections.size() == GsmCallTracker.MAX_CONNECTIONS_PER_CALL;
     }
 
-    //***** Called from CallTracker
+    //***** Called from GsmCallTracker
 
 
-    /** 
+    /**
      * Called when this Call is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
      * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         for (int i = 0, s = connections.size()
                 ; i < s; i++
         ) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
+            GsmConnection cn = (GsmConnection)connections.get(i);
 
             cn.onHangupLocal();
         }
     }
-    
+
     /**
      * Called when it's time to clean up disconnected Connection objects
      */
     void
-    clearDisconnected()
-    {
+    clearDisconnected() {
         for (int i = connections.size() - 1 ; i >= 0 ; i--) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
-            
+            GsmConnection cn = (GsmConnection)connections.get(i);
+
             if (cn.getState() == State.DISCONNECTED) {
                 connections.remove(i);
             }
-        }    
+        }
 
         if (connections.size() == 0) {
             state = State.IDLE;
diff --git a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
similarity index 79%
rename from telephony/java/com/android/internal/telephony/gsm/CallTracker.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
index 2d716bb..5c5090f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
@@ -16,37 +16,34 @@
 
 package com.android.internal.telephony.gsm;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_EDGE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_GPRS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UMTS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UNKNOWN;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Registrant;
-import android.os.RegistrantList;
-import android.os.SystemProperties;
+import android.os.*;
+import android.telephony.gsm.GsmCellLocation;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
-import android.telephony.gsm.GsmCellLocation;
 import android.util.EventLog;
 import android.util.Log;
 
-import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CallTracker;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.gsm.CallFailCause;
+import com.android.internal.telephony.gsm.GsmCall;
+import com.android.internal.telephony.gsm.GsmConnection;
+import com.android.internal.telephony.gsm.GSMPhone;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.*;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.ArrayList;
 
 /**
  * {@hide}
  */
-public final class CallTracker extends Handler
-{
+public final class GsmCallTracker extends CallTracker {
     static final String LOG_TAG = "GSM";
     private static final boolean REPEAT_POLLING = false;
 
@@ -54,59 +51,41 @@
 
     //***** Constants
 
-    static final int POLL_DELAY_MSEC = 250;
     static final int MAX_CONNECTIONS = 7;   // only 7 connections allowed in GSM
     static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call
 
     //***** Instance Variables
-
-    GSMConnection connections[] = new GSMConnection[MAX_CONNECTIONS];
+    GsmConnection connections[] = new GsmConnection[MAX_CONNECTIONS];
     RegistrantList voiceCallEndedRegistrants = new RegistrantList();
     RegistrantList voiceCallStartedRegistrants = new RegistrantList();
 
 
     // connections dropped durin last poll
-    ArrayList<GSMConnection> droppedDuringPoll
-        = new ArrayList<GSMConnection>(MAX_CONNECTIONS);
+    ArrayList<GsmConnection> droppedDuringPoll
+        = new ArrayList<GsmConnection>(MAX_CONNECTIONS);
 
-    GSMCall ringingCall = new GSMCall(this);
+    GsmCall ringingCall = new GsmCall(this);
             // A call that is ringing or (call) waiting
-    GSMCall foregroundCall = new GSMCall(this);
-    GSMCall backgroundCall = new GSMCall(this);
+    GsmCall foregroundCall = new GsmCall(this);
+    GsmCall backgroundCall = new GsmCall(this);
 
-    GSMConnection pendingMO;
+    GsmConnection pendingMO;
     boolean hangupPendingMO;
 
     GSMPhone phone;
-    CommandsInterface cm;
+
     boolean desiredMute = false;    // false = mute off
 
     Phone.State state = Phone.State.IDLE;
 
-    int pendingOperations;
-    boolean needsPoll;
-    Message lastRelevantPoll;
 
 
     //***** Events
 
-    static final int EVENT_POLL_CALLS_RESULT    = 1;
-    static final int EVENT_CALL_STATE_CHANGE    = 2;
-    static final int EVENT_REPOLL_AFTER_DELAY   = 3;
-    static final int EVENT_OPERATION_COMPLETE     = 4;
-    static final int EVENT_GET_LAST_CALL_FAIL_CAUSE = 5;
-
-    static final int EVENT_SWITCH_RESULT        = 8;
-    static final int EVENT_RADIO_AVAILABLE       = 9;
-    static final int EVENT_RADIO_NOT_AVAILABLE       = 10;
-    static final int EVENT_CONFERENCE_RESULT    = 11;
-    static final int EVENT_SEPARATE_RESULT      = 12;
-    static final int EVENT_ECT_RESULT           = 13;
 
     //***** Constructors
 
-    CallTracker (GSMPhone phone)
-    {
+    GsmCallTracker (GSMPhone phone) {
         this.phone = phone;
         cm = phone.mCM;
 
@@ -116,24 +95,56 @@
         cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
     }
 
+    public void dispose() {
+        //Unregister for all events
+        cm.unregisterForCallStateChanged(this);
+        cm.unregisterForOn(this);
+        cm.unregisterForNotAvailable(this);
+
+        for(GsmConnection c : connections) {
+            try {
+                if(c != null) hangup(c);
+            } catch (CallStateException ex) {
+                Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+            }
+        }
+
+        try {
+            if(pendingMO != null) hangup(pendingMO);
+        } catch (CallStateException ex) {
+            Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+        }
+
+        clearDisconnected();
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "GsmCallTracker finalized");
+    }
+
     //***** Instance Methods
 
     //***** Public Methods
-    public void registerForVoiceCallStarted(Handler h, int what, Object obj)
-    {
+    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallStartedRegistrants.add(r);
     }
 
-    public void registerForVoiceCallEnded(Handler h, int what, Object obj)
-    {
+    public void unregisterForVoiceCallStarted(Handler h) {
+        voiceCallStartedRegistrants.remove(h);
+    }
+
+    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallEndedRegistrants.add(r);
     }
 
+    public void unregisterForVoiceCallEnded(Handler h) {
+        voiceCallEndedRegistrants.remove(h);
+    }
+
     private void
-    fakeHoldForegroundBeforeDial()
-    {
+    fakeHoldForegroundBeforeDial() {
         List<Connection> connCopy;
 
         // We need to make a copy here, since fakeHoldBeforeDial()
@@ -141,7 +152,7 @@
         connCopy = (List<Connection>) foregroundCall.connections.clone();
 
         for (int i = 0, s = connCopy.size() ; i < s ; i++) {
-            GSMConnection conn = (GSMConnection)connCopy.get(i);
+            GsmConnection conn = (GsmConnection)connCopy.get(i);
 
             conn.fakeHoldBeforeDial();
         }
@@ -162,7 +173,7 @@
         // The new call must be assigned to the foreground call.
         // That call must be idle, so place anything that's
         // there on hold
-        if (foregroundCall.getState() == Call.State.ACTIVE) {
+        if (foregroundCall.getState() == GsmCall.State.ACTIVE) {
             // this will probably be done by the radio anyway
             // but the dial might fail before this happens
             // and we need to make sure the foreground call is clear
@@ -176,12 +187,12 @@
             fakeHoldForegroundBeforeDial();
         }
 
-        if (foregroundCall.getState() != Call.State.IDLE) {
+        if (foregroundCall.getState() != GsmCall.State.IDLE) {
             //we should have failed in !canDial() above before we get here
             throw new CallStateException("cannot dial in current state");
         }
 
-        pendingMO = new GSMConnection(phone.getContext(), dialString, this, foregroundCall);
+        pendingMO = new GsmConnection(phone.getContext(), dialString, this, foregroundCall);
         hangupPendingMO = false;
 
         if (pendingMO.address == null || pendingMO.address.length() == 0
@@ -208,24 +219,22 @@
 
 
     Connection
-    dial (String dialString) throws CallStateException
-    {
+    dial (String dialString) throws CallStateException {
         return dial(dialString, CommandsInterface.CLIR_DEFAULT);
     }
 
     void
-    acceptCall () throws CallStateException
-    {
+    acceptCall () throws CallStateException {
         // FIXME if SWITCH fails, should retry with ANSWER
         // in case the active/holding call disappeared and this
         // is no longer call waiting
 
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == GsmCall.State.INCOMING) {
             Log.i("phone", "acceptCall: incoming...");
             // Always unmute when answering a new call
             setMute(false);
             cm.acceptCall(obtainCompleteMessage());
-        } else if (ringingCall.getState() == Call.State.WAITING) {
+        } else if (ringingCall.getState() == GsmCall.State.WAITING) {
             setMute(false);
             switchWaitingOrHoldingAndActive();
         } else {
@@ -234,8 +243,7 @@
     }
 
     void
-    rejectCall () throws CallStateException
-    {
+    rejectCall () throws CallStateException {
         // AT+CHLD=0 means "release held or UDUB"
         // so if the phone isn't ringing, this could hang up held
         if (ringingCall.getState().isRinging()) {
@@ -248,7 +256,7 @@
     void
     switchWaitingOrHoldingAndActive() throws CallStateException {
         // Should we bother with this check?
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == GsmCall.State.INCOMING) {
             throw new CallStateException("cannot be in the incoming state");
         } else {
             cm.switchWaitingOrHoldingAndActive(
@@ -257,20 +265,17 @@
     }
 
     void
-    conference() throws CallStateException
-    {
+    conference() throws CallStateException {
         cm.conference(obtainCompleteMessage(EVENT_CONFERENCE_RESULT));
     }
 
     void
-    explicitCallTransfer() throws CallStateException
-    {
+    explicitCallTransfer() throws CallStateException {
         cm.explicitCallTransfer(obtainCompleteMessage(EVENT_ECT_RESULT));
     }
 
     void
-    clearDisconnected()
-    {
+    clearDisconnected() {
         internalClearDisconnected();
 
         updatePhoneState();
@@ -278,17 +283,15 @@
     }
 
     boolean
-    canConference()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING
+    canConference() {
+        return foregroundCall.getState() == GsmCall.State.ACTIVE
+                && backgroundCall.getState() == GsmCall.State.HOLDING
                 && !backgroundCall.isFull()
                 && !foregroundCall.isFull();
     }
 
     boolean
-    canDial()
-    {
+    canDial() {
         boolean ret;
         int serviceState = phone.getServiceState().getState();
 
@@ -302,42 +305,26 @@
     }
 
     boolean
-    canTransfer()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING;
+    canTransfer() {
+        return foregroundCall.getState() == GsmCall.State.ACTIVE
+                && backgroundCall.getState() == GsmCall.State.HOLDING;
     }
 
     //***** Private Instance Methods
 
     private void
-    internalClearDisconnected()
-    {
+    internalClearDisconnected() {
         ringingCall.clearDisconnected();
         foregroundCall.clearDisconnected();
         backgroundCall.clearDisconnected();
     }
 
     /**
-     * @return true if we're idle or there's a call to getCurrentCalls() pending
-     * but nothing else
-     */
-    private boolean
-    checkNoOperationsPending()
-    {
-        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
-                pendingOperations);
-        return pendingOperations == 0;
-    }
-
-
-    /**
      * Obtain a message to use for signalling "invoke getCurrentCalls() when
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage()
-    {
+    obtainCompleteMessage() {
         return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
     }
 
@@ -346,8 +333,7 @@
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage(int what)
-    {
+    obtainCompleteMessage(int what) {
         pendingOperations++;
         lastRelevantPoll = null;
         needsPoll = true;
@@ -358,26 +344,8 @@
         return obtainMessage(what);
     }
 
-    /**
-     * Obtain a complete message that indicates that this operation
-     * does not require polling of getCurrentCalls(). However, if other
-     * operations that do need getCurrentCalls() are pending or are
-     * scheduled while this operation is pending, the invocatoin
-     * of getCurrentCalls() will be postponed until this
-     * operation is also complete.
-     */
-    private Message
-    obtainNoPollCompleteMessage(int what)
-    {
-        pendingOperations++;
-        lastRelevantPoll = null;
-        return obtainMessage(what);
-    }
-
-
     private void
-    operationComplete()
-    {
+    operationComplete() {
         pendingOperations--;
 
         if (DBG_POLL) log("operationComplete: pendingOperations=" +
@@ -388,42 +356,13 @@
             cm.getCurrentCalls(lastRelevantPoll);
         } else if (pendingOperations < 0) {
             // this should never happen
-            Log.e(LOG_TAG,"CallTracker.pendingOperations < 0");
+            Log.e(LOG_TAG,"GsmCallTracker.pendingOperations < 0");
             pendingOperations = 0;
         }
     }
 
     private void
-    pollCallsWhenSafe()
-    {
-        needsPoll = true;
-
-        if (checkNoOperationsPending()) {
-            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
-            cm.getCurrentCalls(lastRelevantPoll);
-        }
-    }
-
-    private void
-    pollCallsAfterDelay()
-    {
-        Message msg = obtainMessage();
-
-        msg.what = EVENT_REPOLL_AFTER_DELAY;
-        sendMessageDelayed(msg, POLL_DELAY_MSEC);
-    }
-
-    private boolean
-    isCommandExceptionRadioNotAvailable(Throwable e)
-    {
-        return e != null && e instanceof CommandException
-                && ((CommandException)e).getCommandError()
-                        == CommandException.Error.RADIO_NOT_AVAILABLE;
-    }
-
-    private void
-    updatePhoneState()
-    {
+    updatePhoneState() {
         Phone.State oldState = state;
 
         if (ringingCall.isRinging()) {
@@ -448,9 +387,8 @@
         }
     }
 
-    private void
-    handlePollCalls(AsyncResult ar)
-    {
+    protected void
+    handlePollCalls(AsyncResult ar) {
         List polledCalls;
 
         if (ar.exception == null) {
@@ -474,7 +412,7 @@
 
         for (int i = 0, curDC = 0, dcSize = polledCalls.size()
                 ; i < connections.length; i++) {
-            GSMConnection conn = connections[i];
+            GsmConnection conn = connections[i];
             DriverCall dc = null;
 
             // polledCall list is sparse
@@ -519,7 +457,7 @@
                         return;
                     }
                 } else {
-                    connections[i] = new GSMConnection(phone.getContext(), dc, this, i);
+                    connections[i] = new GsmConnection(phone.getContext(), dc, this, i);
 
                     // it's a ringing call
                     if (connections[i].getCall() == ringingCall) {
@@ -549,14 +487,14 @@
                 // tracking.
                 droppedDuringPoll.add(conn);
                 // Dropped connections are removed from the CallTracker
-                // list but kept in the GSMCall list
+                // list but kept in the GsmCall list
                 connections[i] = null;
             } else if (conn != null && dc != null && !conn.compareTo(dc)) {
                 // Connection in CLCC response does not match what
                 // we were tracking. Assume dropped call and new call
 
                 droppedDuringPoll.add(conn);
-                connections[i] = new GSMConnection (phone.getContext(), dc, this, i);
+                connections[i] = new GsmConnection (phone.getContext(), dc, this, i);
 
                 if (connections[i].getCall() == ringingCall) {
                     newRinging = connections[i];
@@ -608,7 +546,7 @@
         // cases from the "dropped during poll" list
         // These cases need no "last call fail" reason
         for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) {
-            GSMConnection conn = droppedDuringPoll.get(i);
+            GsmConnection conn = droppedDuringPoll.get(i);
 
             if (conn.isIncoming() && conn.getConnectTime() == 0) {
                 // Missed or rejected call
@@ -630,7 +568,7 @@
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.LOCAL);
             } else if (conn.cause ==
-                    Connection.DisconnectCause.INVALID_NUMBER) {
+                Connection.DisconnectCause.INVALID_NUMBER) {
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
             }
@@ -669,14 +607,7 @@
     }
 
     private void
-    handleRadioAvailable()
-    {
-        pollCallsWhenSafe();
-    }
-
-    private void
-    handleRadioNotAvailable()
-    {
+    handleRadioNotAvailable() {
         // handlePollCalls will clear out its
         // call list when it gets the CommandException
         // error result from this
@@ -684,8 +615,7 @@
     }
 
     private void
-    dumpState()
-    {
+    dumpState() {
         List l;
 
         Log.i(LOG_TAG,"Phone State:" + state);
@@ -713,14 +643,13 @@
 
     }
 
-    //***** Called from GSMConnection
+    //***** Called from GsmConnection
 
     /*package*/ void
-    hangup (GSMConnection conn) throws CallStateException
-    {
+    hangup (GsmConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("GsmConnection " + conn
+                                    + "does not belong to GsmCallTracker " + this);
         }
 
         if (conn == pendingMO) {
@@ -735,7 +664,7 @@
             } catch (CallStateException ex) {
                 // Ignore "connection not found"
                 // Call may have hung up already
-                Log.w(LOG_TAG,"CallTracker WARN: hangup() on absent connection "
+                Log.w(LOG_TAG,"GsmCallTracker WARN: hangup() on absent connection "
                                 + conn);
             }
         }
@@ -744,11 +673,10 @@
     }
 
     /*package*/ void
-    separate (GSMConnection conn) throws CallStateException
-    {
+    separate (GsmConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("GsmConnection " + conn
+                                    + "does not belong to GsmCallTracker " + this);
         }
         try {
             cm.separateConnection (conn.getGSMIndex(),
@@ -756,7 +684,7 @@
         } catch (CallStateException ex) {
             // Ignore "connection not found"
             // Call may have hung up already
-            Log.w(LOG_TAG,"CallTracker WARN: separate() on absent connection "
+            Log.w(LOG_TAG,"GsmCallTracker WARN: separate() on absent connection "
                           + conn);
         }
     }
@@ -764,24 +692,21 @@
     //***** Called from GSMPhone
 
     /*package*/ void
-    setMute(boolean mute)
-    {
+    setMute(boolean mute) {
         desiredMute = mute;
         cm.setMute(desiredMute, null);
     }
 
     /*package*/ boolean
-    getMute()
-    {
+    getMute() {
         return desiredMute;
     }
 
 
-    //***** Called from GSMCall
+    //***** Called from GsmCall
 
     /* package */ void
-    hangup (GSMCall call) throws CallStateException
-    {
+    hangup (GsmCall call) throws CallStateException {
         if (call.getConnections().size() == 0) {
             throw new CallStateException("no connections in call");
         }
@@ -794,7 +719,7 @@
                 if (Phone.DEBUG_PHONE) {
                     log("(foregnd) hangup dialing or alerting...");
                 }
-                hangup((GSMConnection)(call.getConnections().get(0)));
+                hangup((GsmConnection)(call.getConnections().get(0)));
             } else {
                 hangupForegroundResumeBackground();
             }
@@ -808,8 +733,8 @@
                 hangupWaitingOrBackground();
             }
         } else {
-            throw new RuntimeException ("Call " + call +
-                    "does not belong to CallTracker " + this);
+            throw new RuntimeException ("GsmCall " + call +
+                    "does not belong to GsmCallTracker " + this);
         }
 
         call.onHangupLocal();
@@ -827,11 +752,11 @@
         cm.hangupForegroundResumeBackground(obtainCompleteMessage());
     }
 
-    void hangupConnectionByIndex(GSMCall call, int index)
+    void hangupConnectionByIndex(GsmCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
+            GsmConnection cn = (GsmConnection)call.connections.get(i);
             if (cn.getGSMIndex() == index) {
                 cm.hangupConnection(index, obtainCompleteMessage());
                 return;
@@ -841,11 +766,11 @@
         throw new CallStateException("no gsm index found");
     }
 
-    void hangupAllConnections(GSMCall call) throws CallStateException{
+    void hangupAllConnections(GsmCall call) throws CallStateException{
         try {
             int count = call.connections.size();
             for (int i = 0; i < count; i++) {
-                GSMConnection cn = (GSMConnection)call.connections.get(i);
+                GsmConnection cn = (GsmConnection)call.connections.get(i);
                 cm.hangupConnection(cn.getGSMIndex(), obtainCompleteMessage());
             }
         } catch (CallStateException ex) {
@@ -854,11 +779,11 @@
     }
 
     /* package */
-    GSMConnection getConnectionByIndex(GSMCall call, int index)
+    GsmConnection getConnectionByIndex(GsmCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
+            GsmConnection cn = (GsmConnection)call.connections.get(i);
             if (cn.getGSMIndex() == index) {
                 return cn;
             }
@@ -884,8 +809,7 @@
     //****** Overridden from Handler
 
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
 
         switch (msg.what) {
@@ -952,7 +876,7 @@
                 for (int i = 0, s =  droppedDuringPoll.size()
                         ; i < s ; i++
                 ) {
-                    GSMConnection conn = droppedDuringPoll.get(i);
+                    GsmConnection conn = droppedDuringPoll.get(i);
 
                     conn.onRemoteDisconnect(causeCode);
                 }
@@ -978,7 +902,7 @@
         }
     }
 
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[CallTracker] " + msg);
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[GsmCallTracker] " + msg);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
similarity index 85%
rename from telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index 4777892..2b2f077 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -15,39 +15,39 @@
  */
 
 package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
-
 import android.content.Context;
+import android.os.AsyncResult;
 import android.os.Handler;
-import android.os.PowerManager;
-import android.os.Registrant;
 import android.os.Looper;
 import android.os.Message;
-import android.os.AsyncResult;
+import android.os.PowerManager;
+import android.os.Registrant;
 import android.os.SystemClock;
-import android.util.Log;
 import android.util.Config;
+import android.util.Log;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 
+import com.android.internal.telephony.*;
+
 /**
  * {@hide}
  */
-public class GSMConnection extends Connection {
+public class GsmConnection extends Connection {
     static final String LOG_TAG = "GSM";
 
     //***** Instance Variables
 
-    CallTracker owner;
-    GSMCall parent;
+    GsmCallTracker owner;
+    GsmCall parent;
 
     String address;     // MAY BE NULL!!!
     String dialString;          // outgoing calls only
-    String postDialString;      // outgoing calls only    
+    String postDialString;      // outgoing calls only
     boolean isIncoming;
-    boolean disconnected; 
+    boolean disconnected;
 
-    int index;          // index in CallTracker.connections[], -1 if unassigned
+    int index;          // index in GsmCallTracker.connections[], -1 if unassigned
                         // The GSM index is 1 + this
 
     /*
@@ -65,7 +65,7 @@
      */
     long connectTimeReal;
     long duration;
-    long holdingStartTime;  // The time when the Connection last transitioned 
+    long holdingStartTime;  // The time when the Connection last transitioned
                             // into HOLDING
 
     int nextPostDialChar;       // index into postDialString
@@ -95,8 +95,8 @@
         MyHandler(Looper l) {super(l);}
 
         public void
-        handleMessage(Message msg)
-        {
+        handleMessage(Message msg) {
+
             switch (msg.what) {
                 case EVENT_NEXT_POST_DIAL:
                 case EVENT_DTMF_DONE:
@@ -114,11 +114,10 @@
 
     /** This is probably an MT call that we first saw in a CLCC response */
     /*package*/
-    GSMConnection (Context context, DriverCall dc, CallTracker ct, int index)
-    {
+    GsmConnection (Context context, DriverCall dc, GsmCallTracker ct, int index) {
         createWakeLock(context);
         acquireWakeLock();
-
+		
         owner = ct;
         h = new MyHandler(owner.getLooper());
 
@@ -136,11 +135,10 @@
 
     /** This is an MO call, created when dialing */
     /*package*/
-    GSMConnection (Context context, String dialString, CallTracker ct, GSMCall parent)
-    {
+    GsmConnection (Context context, String dialString, GsmCallTracker ct, GsmCall parent) {
         createWakeLock(context);
         acquireWakeLock();
-
+		
         owner = ct;
         h = new MyHandler(owner.getLooper());
 
@@ -155,18 +153,19 @@
         createTime = System.currentTimeMillis();
 
         this.parent = parent;
-        parent.attachFake(this, Call.State.DIALING);
+        parent.attachFake(this, GsmCall.State.DIALING);
     }
-    
+
+    public void dispose() {
+    }
+
     static boolean
-    equalsHandlesNulls (Object a, Object b)
-    {
+    equalsHandlesNulls (Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
 
     /*package*/ boolean
-    compareTo(DriverCall c)
-    {
+    compareTo(DriverCall c) {
         // On mobile originated (MO) calls, the phone number may have changed
         // due to a SIM Toolkit call control modification.
         //
@@ -178,43 +177,35 @@
         // no control over when they begin, so we might as well
 
         String cAddress = PhoneNumberUtils.stringFromStringAndTOA(c.number, c.TOA);
-        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress); 
+        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return (isIncoming ? "incoming" : "outgoing");
     }
 
-    public String getAddress()
-    {
-        return address; 
+    public String getAddress() {
+        return address;
     }
 
-
-    public Call getCall()
-    {
+    public GsmCall getCall() {
         return parent;
     }
 
-    public long getCreateTime()
-    {
+    public long getCreateTime() {
         return createTime;
     }
 
-    public long getConnectTime()
-    {
+    public long getConnectTime() {
         return connectTime;
     }
 
-    public long getDisconnectTime()
-    {
+    public long getDisconnectTime() {
         return disconnectTime;
     }
 
-    public long getDurationMillis()
-    {
+    public long getDurationMillis() {
         if (connectTimeReal == 0) {
             return 0;
         } else if (duration == 0) {
@@ -224,9 +215,8 @@
         }
     }
 
-    public long getHoldDurationMillis()
-    {
-        if (getState() != Call.State.HOLDING) {
+    public long getHoldDurationMillis() {
+        if (getState() != GsmCall.State.HOLDING) {
             // If not holding, return 0
             return 0;
         } else {
@@ -234,52 +224,45 @@
         }
     }
 
-    public DisconnectCause getDisconnectCause()
-    {
+    public DisconnectCause getDisconnectCause() {
         return cause;
     }
 
-    public boolean isIncoming()
-    {
+    public boolean isIncoming() {
         return isIncoming;
     }
 
-    public Call.State getState()
-    {
+    public GsmCall.State getState() {
         if (disconnected) {
-            return Call.State.DISCONNECTED;
-        } else {   
+            return GsmCall.State.DISCONNECTED;
+        } else {
             return super.getState();
         }
     }
 
-    public void hangup() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void hangup() throws CallStateException {
+        if (!disconnected) {
             owner.hangup(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public void separate() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void separate() throws CallStateException {
+        if (!disconnected) {
             owner.separate(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public PostDialState getPostDialState()
-    {
+    public PostDialState getPostDialState() {
         return postDialState;
     }
 
-    public void proceedAfterWaitChar()
-    {
+    public void proceedAfterWaitChar() {
         if (postDialState != PostDialState.WAIT) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "GsmConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WAIT but was " + postDialState);
             return;
         }
@@ -288,10 +271,10 @@
 
         processNextPostDialChar();
     }
-    
+
     public void proceedAfterWildChar(String str) {
         if (postDialState != PostDialState.WILD) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "GsmConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WILD but was " + postDialState);
             return;
         }
@@ -328,38 +311,35 @@
             postDialString = buf.toString();
             nextPostDialChar = 0;
             if (Phone.DEBUG_PHONE) {
-                log("proceedAfterWildChar: new postDialString is " + 
+                log("proceedAfterWildChar: new postDialString is " +
                         postDialString);
             }
 
             processNextPostDialChar();
         }
     }
-    
-    public void cancelPostDial()
-    {
+
+    public void cancelPostDial() {
         setPostDialState(PostDialState.CANCELLED);
     }
 
-    /** 
+    /**
      * Called when this Connection is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
-     * but no response has yet been received so update() has not yet been called 
+     * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         cause = DisconnectCause.LOCAL;
     }
 
     DisconnectCause
-    disconnectCauseFromCode(int causeCode)
-    {
+    disconnectCauseFromCode(int causeCode) {
         /**
          * See 22.001 Annex F.4 for mapping of cause codes
          * to local tones
          */
-    
+
         switch (causeCode) {
             case CallFailCause.USER_BUSY:
                 return DisconnectCause.BUSY;
@@ -382,7 +362,7 @@
                 return DisconnectCause.FDN_BLOCKED;
 
             case CallFailCause.ERROR_UNSPECIFIED:
-            case CallFailCause.NORMAL_CLEARING: 
+            case CallFailCause.NORMAL_CLEARING:
             default:
                 GSMPhone phone = owner.phone;
                 int serviceState = phone.getServiceState().getState();
@@ -391,8 +371,8 @@
                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
                         || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
                     return DisconnectCause.OUT_OF_SERVICE;
-                } else if (phone.getSimCard().getState() != GsmSimCard.State.READY) {
-                    return DisconnectCause.SIM_ERROR;
+                } else if (phone.getIccCard().getState() != SimCard.State.READY) {
+                    return DisconnectCause.ICC_ERROR;
                 } else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
                     if (phone.mSST.rs.isCsRestricted()) {
                         return DisconnectCause.CS_RESTRICTED; 
@@ -410,20 +390,18 @@
     }
 
     /*package*/ void
-    onRemoteDisconnect(int causeCode)
-    {
+    onRemoteDisconnect(int causeCode) {
         onDisconnect(disconnectCauseFromCode(causeCode));
     }
 
     /** Called when the radio indicates the connection has been disconnected */
     /*package*/ void
-    onDisconnect(DisconnectCause cause)
-    {
+    onDisconnect(DisconnectCause cause) {
         this.cause = cause;
-        
-        if (!disconnected) {        
+
+        if (!disconnected) {
             index = -1;
-            
+
             disconnectTime = System.currentTimeMillis();
             duration = SystemClock.elapsedRealtime() - connectTimeReal;
             disconnected = true;
@@ -434,7 +412,7 @@
             owner.phone.notifyDisconnect(this);
 
             if (parent != null) {
-                parent.connectionDisconnected(this);            
+                parent.connectionDisconnected(this);
             }
         }
         releaseWakeLock();
@@ -443,10 +421,10 @@
     // Returns true if state has changed, false if nothing changed
     /*package*/ boolean
     update (DriverCall dc) {
-        GSMCall newParent;
+        GsmCall newParent;
         boolean changed = false;
         boolean wasConnectingInOrOut = isConnectingInOrOut();
-        boolean wasHolding = (getState() == Call.State.HOLDING);
+        boolean wasHolding = (getState() == GsmCall.State.HOLDING);
 
         newParent = parentFromDCState(dc.state);
 
@@ -484,7 +462,7 @@
             onConnectedInOrOut();
         }
 
-        if (changed && !wasHolding && (getState() == Call.State.HOLDING)) {
+        if (changed && !wasHolding && (getState() == GsmCall.State.HOLDING)) {
             // We've transitioned into HOLDING
             onStartedHolding();
         }
@@ -499,14 +477,13 @@
      * HOLDING in the backgroundCall
      */
     void
-    fakeHoldBeforeDial()
-    {
+    fakeHoldBeforeDial() {
         if (parent != null) {
             parent.detach(this);
         }
 
         parent = owner.backgroundCall;
-        parent.attachFake(this, Call.State.HOLDING);
+        parent.attachFake(this, GsmCall.State.HOLDING);
 
         onStartedHolding();
     }
@@ -552,28 +529,27 @@
      * should be ignored
      */
     private boolean
-    processPostDialChar(char c)
-    {
+    processPostDialChar(char c) {
         if (PhoneNumberUtils.is12Key(c)) {
             owner.cm.sendDtmf(c, h.obtainMessage(EVENT_DTMF_DONE));
         } else if (c == PhoneNumberUtils.PAUSE) {
             // From TS 22.101:
 
-            // "The first occurrence of the "DTMF Control Digits Separator" 
-            //  shall be used by the ME to distinguish between the addressing 
+            // "The first occurrence of the "DTMF Control Digits Separator"
+            //  shall be used by the ME to distinguish between the addressing
             //  digits (i.e. the phone number) and the DTMF digits...."
 
             if (nextPostDialChar == 1) {
                 // The first occurrence.
                 // We don't need to pause here, but wait for just a bit anyway
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_FIRST_MILLIS);
             } else {
                 // It continues...
-                // "Upon subsequent occurrences of the separator, the UE shall 
-                //  pause again for 3 seconds (\u00B1 20 %) before sending any 
+                // "Upon subsequent occurrences of the separator, the UE shall
+                //  pause again for 3 seconds (\u00B1 20 %) before sending any
                 //  further DTMF digits."
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_MILLIS);
             }
         } else if (c == PhoneNumberUtils.WAIT) {
@@ -588,9 +564,8 @@
     }
 
     public String
-    getRemainingPostDialString()
-    {
-        if (postDialState == PostDialState.CANCELLED 
+    getRemainingPostDialString() {
+        if (postDialState == PostDialState.CANCELLED
             || postDialState == PostDialState.COMPLETE
             || postDialString == null
             || postDialString.length() <= nextPostDialChar
@@ -617,8 +592,7 @@
     }
 
     private void
-    processNextPostDialChar()
-    {
+    processNextPostDialChar() {
         char c = 0;
         Registrant postDialHandler;
 
@@ -655,7 +629,8 @@
 
         Message notifyMessage;
 
-        if (postDialHandler != null && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
+        if (postDialHandler != null
+                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
             // The AsyncResult.result is the Connection object
             PostDialState state = postDialState;
             AsyncResult ar = AsyncResult.forMessage(notifyMessage);
@@ -668,14 +643,6 @@
             //Log.v("GSM", "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
             notifyMessage.sendToTarget();
         }
-        /*
-        else {
-            if (postDialHandler == null)
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler is NULL!");
-            else
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler.messageForRegistrant() returned NULL!");
-        }
-        */
     }
 
 
@@ -683,16 +650,14 @@
      *  and outgoing calls
      */
     private boolean
-    isConnectingInOrOut()
-    {
-        return parent == null || parent == owner.ringingCall 
-            || parent.state == Call.State.DIALING 
-            || parent.state == Call.State.ALERTING;
+    isConnectingInOrOut() {
+        return parent == null || parent == owner.ringingCall
+            || parent.state == GsmCall.State.DIALING
+            || parent.state == GsmCall.State.ALERTING;
     }
 
-    private GSMCall
-    parentFromDCState (DriverCall.State state)
-    {
+    private GsmCall
+    parentFromDCState (DriverCall.State state) {
         switch (state) {
             case ACTIVE:
             case DIALING:
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
similarity index 68%
rename from telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 02a6841..9e6ebc4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -50,8 +50,12 @@
 import android.util.EventLog;
 import android.util.Log;
 
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.PdpConnection.PdpFailCause;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.TelephonyEventLog;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -59,45 +63,11 @@
 /**
  * {@hide}
  */
-final class DataConnectionTracker extends Handler
-{
+public final class GsmDataConnectionTracker extends DataConnectionTracker {
     private static final String LOG_TAG = "GSM";
     private static final boolean DBG = true;
 
     /**
-     * IDLE: ready to start data connection setup, default state
-     * INITING: state of issued setupDefaultPDP() but not finish yet
-     * CONNECTING: state of issued startPppd() but not finish yet
-     * SCANNING: data connection fails with one apn but other apns are available
-     *           ready to start data connection on other apns (before INITING)
-     * CONNECTED: IP connection is setup
-     * DISCONNECTING: PdpConnection.disconnect() has been called, but PDP
-     *                context is not yet deactivated
-     * FAILED: data connection fail for all apns settings
-     *
-     * getDataConnectionState() maps State to DataState
-     *      FAILED or IDLE : DISCONNECTED
-     *      INITING or CONNECTING or SCANNING: CONNECTING
-     *      CONNECTED : CONNECTED or DISCONNECTING
-     */
-    enum State {
-        IDLE,
-        INITING,
-        CONNECTING,
-        SCANNING,
-        CONNECTED,
-        DISCONNECTING,
-        FAILED
-    }
-
-    enum Activity {
-        NONE,
-        DATAIN,
-        DATAOUT,
-        DATAINANDOUT
-    }
-
-    /**
      * Handles changes to the APN db.
      */
     private class ApnChangeObserver extends ContentObserver {
@@ -113,20 +83,12 @@
 
     //***** Instance Variables
 
-    GSMPhone phone;
     INetStatService netstat;
-    State state = State.IDLE;
-    Activity activity = Activity.NONE;
-    boolean netStatPollEnabled = false;
     // Indicates baseband will not auto-attach
     private boolean noAutoAttach = false;
     long nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
-    Handler mDataConnectionTracker = null;
     private ContentResolver mResolver;
 
-    long txPkts, rxPkts, sentSinceLastRecv;
-    int netStatPollPeriod;
-    private int mNoRecvPollCount = 0;
     private boolean mPingTestActive = false;
     // Count of PDP reset attempts; reset when we see incoming,
     // call reRegisterNetwork, or pingTest succeeds.
@@ -156,10 +118,7 @@
     /**
      * pdpList holds all the PDP connection, i.e. IP Link in GPRS
      */
-    private ArrayList<PdpConnection> pdpList;
-
-    /** CID of active PDP */
-    int cidActive;
+    private ArrayList<DataConnection> pdpList;
 
     /** Currently requested APN type */
     private String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
@@ -172,16 +131,11 @@
 
     private static int APN_DEFAULT_ID = 0;
     private static int APN_MMS_ID = 1;
-    private static int APN_NUM_TYPES = 2;
+    private static int APN_SUPL_ID = 2;
+    private static int APN_NUM_TYPES = 3;
 
     private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
 
-    /** wifi connection status will be updated by sticky intent */
-    private boolean mIsWifiConnected = false;
-
-    /** Intent sent when the reconnect alarm fires. */
-    private PendingIntent mReconnectIntent = null;
-    
     /** Is packet service restricted by network */
     private boolean mIsPsRestricted = false;
 
@@ -195,70 +149,11 @@
     private static final int PDP_CONNECTION_POOL_SIZE = 1;
 
     private static final int POLL_PDP_MILLIS = 5 * 1000;
-    private static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
-    /** Cap out with 1 hour retry interval. */
-    private static final int RECONNECT_DELAY_MAX_MILLIS = 60 * 60 * 1000;
 
-    /** Slow poll when attempting connection recovery. */
-    private static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
-
-    /** Default ping deadline, in seconds. */
-    private static final int DEFAULT_PING_DEADLINE = 5;
-    /** Default max failure count before attempting to network re-registration. */
-    private static final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
-
-    /**
-     * After detecting a potential connection problem, this is the max number
-     * of subsequent polls before attempting a radio reset.  At this point,
-     * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
-     * poll for about 2 more minutes.
-     */
-    private static final int NO_RECV_POLL_LIMIT = 24;
-
-    // 1 sec. default polling interval when screen is on.
-    private static final int POLL_NETSTAT_MILLIS = 1000;
-    // 10 min. default polling interval when screen is off.
-    private static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
-    // 2 min for round trip time
-    private static final int POLL_LONGEST_RTT = 120 * 1000;
-    // 10 for packets without ack
-    private static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
-    // how long to wait before switching back to default APN
-    private static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
-    // system property that can override the above value
-    private static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
-    // represents an invalid IP address
-    private static final String NULL_IP = "0.0.0.0";
-
+    //WINK:TODO: Teleca, is this really gsm specific, what about CDMA?
     private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
     private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
 
-
-    //***** Event Codes
-    static final int EVENT_DATA_SETUP_COMPLETE = 1;
-    static final int EVENT_RADIO_AVAILABLE = 3;
-    static final int EVENT_RECORDS_LOADED = 4;
-    static final int EVENT_TRY_SETUP_DATA = 5;
-    static final int EVENT_PDP_STATE_CHANGED = 6;
-    static final int EVENT_POLL_PDP = 7;
-    static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
-    static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
-    static final int EVENT_VOICE_CALL_STARTED = 14;
-    static final int EVENT_VOICE_CALL_ENDED = 15;
-    static final int EVENT_GPRS_DETACHED = 19;
-    static final int EVENT_LINK_STATE_CHANGED = 20;
-    static final int EVENT_ROAMING_ON = 21;
-    static final int EVENT_ROAMING_OFF = 22;
-    static final int EVENT_ENABLE_NEW_APN = 23;
-    static final int EVENT_RESTORE_DEFAULT_APN = 24;
-    static final int EVENT_DISCONNECT_DONE = 25;
-    static final int EVENT_GPRS_ATTACHED = 26;
-    static final int EVENT_START_NETSTAT_POLL = 27;
-    static final int EVENT_START_RECOVERY = 28;
-    static final int EVENT_APN_CHANGED = 29;
-    static final int EVENT_PS_RESTRICT_ENABLED = 30;
-    static final int EVENT_PS_RESTRICT_DISABLED = 31;
-
     static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
     static final String APN_ID = "apn_id";
     private boolean canSetPreferApn = false;
@@ -307,21 +202,21 @@
 
     //***** Constructor
 
-    DataConnectionTracker(GSMPhone phone)
-    {
-        this.phone = phone;
-        phone.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
-        phone.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
-        phone.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
-        phone.mCM.registerForPDPStateChanged (this, EVENT_PDP_STATE_CHANGED, null);
-        phone.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
-        phone.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
-        phone.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
-        phone.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
-        phone.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
-        phone.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
-        phone.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
-        phone.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
+    GsmDataConnectionTracker(GSMPhone p) {
+        super(p);
+
+        p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
+        p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+        p.mCM.registerForDataStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
+        p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
+        p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
+        p.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
+        p.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
+        p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
+        p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+        p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
+        p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
 
         this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
 
@@ -332,14 +227,14 @@
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
 
-        phone.getContext().registerReceiver(mIntentReceiver, filter, null, phone.h);
+        p.getContext().registerReceiver(mIntentReceiver, filter, null, p.h);
 
 
         mDataConnectionTracker = this;
         mResolver = phone.getContext().getContentResolver();
 
         apnObserver = new ApnChangeObserver();
-        phone.getContext().getContentResolver().registerContentObserver(
+        p.getContext().getContentResolver().registerContentObserver(
                 Telephony.Carriers.CONTENT_URI, true, apnObserver);
 
         createAllPdpList();
@@ -351,6 +246,31 @@
         noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
     }
 
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForAvailable(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        ((GSMPhone) phone).mSIMRecords.unregisterForRecordsLoaded(this);
+        phone.mCM.unregisterForDataStateChanged(this);
+        ((GSMPhone) phone).mCT.unregisterForVoiceCallEnded(this);
+        ((GSMPhone) phone).mCT.unregisterForVoiceCallStarted(this);
+        ((GSMPhone) phone).mSST.unregisterForGprsAttached(this);
+        ((GSMPhone) phone).mSST.unregisterForGprsDetached(this);
+        ((GSMPhone) phone).mSST.unregisterForRoamingOn(this);
+        ((GSMPhone) phone).mSST.unregisterForRoamingOff(this);
+        ((GSMPhone) phone).mSST.unregisterForPsRestrictedEnabled(this);
+        ((GSMPhone) phone).mSST.unregisterForPsRestrictedDisabled(this);
+        
+        phone.getContext().unregisterReceiver(this.mIntentReceiver);
+        phone.getContext().getContentResolver().unregisterContentObserver(this.apnObserver);
+
+        destroyAllPdpList();
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "GsmDataConnectionTracker finalized");
+    }
+
     void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (state != s) {
@@ -375,19 +295,6 @@
         }
     }
 
-    String getStateInString() {
-        switch (state) {
-            case IDLE:          return "IDLE";
-            case INITING:       return "INIT";
-            case CONNECTING:    return "CING";
-            case SCANNING:      return "SCAN";
-            case CONNECTED:     return "CNTD";
-            case DISCONNECTING: return "DING";
-            case FAILED:        return "FAIL";
-            default:            return "ERRO";
-        }
-    }
-
     String[] getActiveApnTypes() {
         String[] result;
         if (mActiveApn != null) {
@@ -399,7 +306,7 @@
         return result;
     }
 
-    String getActiveApnString() {
+    protected String getActiveApnString() {
         String result = null;
         if (mActiveApn != null) {
             result = mActiveApn.apn;
@@ -409,18 +316,20 @@
 
     /**
      * Ensure that we are connected to an APN of the specified type.
-     * @param type the APN type (currently the only valid value
-     * is {@link Phone#APN_TYPE_MMS})
+     * @param type the APN type (currently the only valid values
+     * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
      * @return the result of the operation. Success is indicated by
      * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or
      * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast
      * will be sent by the ConnectivityManager when a connection to
      * the APN has been established.
      */
-    int enableApnType(String type) {
-        if (!TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+    protected int enableApnType(String type) {
+        if (!TextUtils.equals(type, Phone.APN_TYPE_MMS) &&
+                !TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
             return Phone.APN_REQUEST_FAILED;
         }
+
         // If already active, return
         Log.d(LOG_TAG, "enableApnType("+type+")");
         if (isApnTypeActive(type)) {
@@ -453,12 +362,15 @@
      * The APN of the specified type is no longer needed. Ensure that if
      * use of the default APN has not been explicitly disabled, we are connected
      * to the default APN.
-     * @param type the APN type. The only valid value currently is {@link Phone#APN_TYPE_MMS}.
+     * @param type the APN type. The only valid values are currently 
+     * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
      * @return
      */
-    int disableApnType(String type) {
+    protected int disableApnType(String type) {
         Log.d(LOG_TAG, "disableApnType("+type+")");
-        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+        if ((TextUtils.equals(type, Phone.APN_TYPE_MMS) ||
+                TextUtils.equals(type, Phone.APN_TYPE_SUPL))
+                && isEnabled(type)) {
             removeMessages(EVENT_RESTORE_DEFAULT_APN);
             setEnabled(type, false);
             if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
@@ -489,16 +401,15 @@
      *  2. registered to gprs service
      *  3. user doesn't explicitly disable data service
      *  4. wifi is not on
-     *  5. packet service is not restricted
      *
      * @return false while no data connection if all above requirements are met.
      */
-    boolean isDataConnectionAsDesired() {
+    public boolean isDataConnectionAsDesired() {
         boolean roaming = phone.getServiceState().getRoaming();
 
-        if (phone.mSIMRecords.getRecordsLoaded() &&
-            phone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
-            (!roaming || getDataOnRoamingEnabled()) &&
+        if (((GSMPhone) phone).mSIMRecords.getRecordsLoaded() &&
+                ((GSMPhone) phone).mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
+                (!roaming || getDataOnRoamingEnabled()) &&
             !mIsWifiConnected && 
             !mIsPsRestricted ) {
             return (state == State.CONNECTED);
@@ -527,6 +438,8 @@
             return dataEnabled[APN_DEFAULT_ID];
         } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
             return dataEnabled[APN_MMS_ID];
+        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
+            return dataEnabled[APN_SUPL_ID];
         } else {
             return false;
         }
@@ -538,9 +451,12 @@
             dataEnabled[APN_DEFAULT_ID] = enable;
         } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
             dataEnabled[APN_MMS_ID] = enable;
+        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
+            dataEnabled[APN_SUPL_ID] = enable;
         }
         Log.d(LOG_TAG, "dataEnabled[DEFAULT_APN]=" + dataEnabled[APN_DEFAULT_ID] +
-                " dataEnabled[MMS_APN]=" + dataEnabled[APN_MMS_ID]);
+                " dataEnabled[MMS_APN]=" + dataEnabled[APN_MMS_ID] +
+                " dataEnabled[SUPL_APN]=" + dataEnabled[APN_SUPL_ID]);
     }
 
     /**
@@ -564,17 +480,20 @@
             return trySetupData(Phone.REASON_DATA_ENABLED);
         } else if (!enable) {
             setEnabled(Phone.APN_TYPE_DEFAULT, false);
-            // Don't tear down if there is an active APN and it handles MMS.
+            // Don't tear down if there is an active APN and it handles MMS or SUPL.
             // TODO: This isn't very general.
-            if (!isApnTypeActive(Phone.APN_TYPE_MMS) || !isEnabled(Phone.APN_TYPE_MMS)) {
-                cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
-                return true;
+            if ((isApnTypeActive(Phone.APN_TYPE_MMS) && isEnabled(Phone.APN_TYPE_MMS)) ||
+                (isApnTypeActive(Phone.APN_TYPE_SUPL) && isEnabled(Phone.APN_TYPE_SUPL))) {
+                return false;
             }
-            return false;
-        } else // isEnabled && enable
+            cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
             return true;
+        } else {
+            // isEnabled && enable
+            return true;
+        }
     }
-
+    
     /**
      * Simply tear down data connections due to radio off 
      * and don't setup again.
@@ -582,7 +501,7 @@
     public void cleanConnectionBeforeRadioOff() {
         cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
     }
-    
+
     /**
      * Report the current state of data connectivity (enabled or disabled) for
      * the default APN.
@@ -599,34 +518,14 @@
      * {@code true} otherwise.
      */
     public boolean getAnyDataEnabled() {
-        return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID];
+        return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID];
     }
 
-    //The data roaming setting is now located in the shared preferences.
-    //  See if the requested preference value is the same as that stored in
-    //  the shared values.  If it is not, then update it.
-    public void setDataOnRoamingEnabled(boolean enabled) {
-        if (getDataOnRoamingEnabled() != enabled) {
-            Settings.Secure.putInt(phone.getContext().getContentResolver(),
-                Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
-        }
-        Message roamingMsg = phone.getServiceState().getRoaming() ?
-            obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
-        sendMessage(roamingMsg);
-    }
-
-    //Retrieve the data roaming setting from the shared preferences.
-    public boolean getDataOnRoamingEnabled() {
-        try {
-            return Settings.Secure.getInt(phone.getContext().getContentResolver(),
-                Settings.Secure.DATA_ROAMING) > 0;
-        } catch (SettingNotFoundException snfe) {
-            return false;
-        }
-    }
-
-    public ArrayList<PdpConnection> getAllPdps() {
-        ArrayList<PdpConnection> pdps = (ArrayList<PdpConnection>)pdpList.clone();
+    /**
+     * Formerly this method was ArrayList<PdpConnection> getAllPdps()
+     */
+    public ArrayList<DataConnection> getAllDataConnections() {
+        ArrayList<DataConnection> pdps = (ArrayList<DataConnection>)pdpList.clone();
         return pdps;
     }
 
@@ -640,8 +539,7 @@
      * Invoked when ServiceStateTracker observes a transition from GPRS
      * attach to detach.
      */
-    private void onGprsDetached()
-    {
+    protected void onGprsDetached() {
         /*
          * We presently believe it is unnecessary to tear down the PDP context
          * when GPRS detaches, but we should stop the network polling.
@@ -663,8 +561,7 @@
         }
     }
 
-    private boolean trySetupData(String reason)
-    {
+    private boolean trySetupData(String reason) {
         if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
 
         Log.d(LOG_TAG, "[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
@@ -679,13 +576,14 @@
             return true;
         }
 
-        int gprsState = phone.mSST.getCurrentGprsState();
+        int gprsState = ((GSMPhone) phone).mSST.getCurrentGprsState();
         boolean roaming = phone.getServiceState().getRoaming();
 
         if ((state == State.IDLE || state == State.SCANNING)
                 && (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach)
-                && phone.mSIMRecords.getRecordsLoaded()
-                && phone.getState() == Phone.State.IDLE
+                && ((GSMPhone) phone).mSIMRecords.getRecordsLoaded()
+                && ( ((GSMPhone) phone).mSST.isConcurrentVoiceAndData() ||
+                     phone.getState() == Phone.State.IDLE )
                 && isDataAllowed()
                 && !mIsPsRestricted ) {
 
@@ -693,7 +591,7 @@
                 waitingApns = buildWaitingApns();
                 if (waitingApns.isEmpty()) {
                     if (DBG) log("No APN found");
-                    notifyNoData(PdpConnection.PdpFailCause.BAD_APN);
+                    notifyNoData(PdpConnection.FailCause.BAD_APN);
                     return false;
                 } else {
                     log ("Create from allApns : " + apnListToString(allApns));
@@ -709,8 +607,8 @@
                 log("trySetupData: Not ready for data: " +
                     " dataState=" + state +
                     " gprsState=" + gprsState +
-                    " sim=" + phone.mSIMRecords.getRecordsLoaded() +
-                    " UMTS=" + phone.mSST.isConcurrentVoiceAndData() +
+                    " sim=" + ((GSMPhone) phone).mSIMRecords.getRecordsLoaded() +
+                    " UMTS=" + ((GSMPhone) phone).mSST.isConcurrentVoiceAndData() +
                     " phoneState=" + phone.getState() +
                     " dataEnabled=" + getAnyDataEnabled() +
                     " roaming=" + roaming +
@@ -740,7 +638,8 @@
             mReconnectIntent = null;
         }
 
-        for (PdpConnection pdp : pdpList) {
+        for (DataConnection conn : pdpList) {
+            PdpConnection pdp = (PdpConnection) conn;
             if (tearDown) {
                 Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
                 pdp.disconnect(msg);
@@ -762,7 +661,7 @@
          * IDLE before the code below runs. If we didn't check
          * for that, future calls to trySetupData would fail,
          * and we would never get out of the DISCONNECTING state.
-         */
+         */ 
         if (!tearDown) {
             setState(State.IDLE);
             phone.notifyDataConnection(reason);
@@ -814,8 +713,9 @@
     }
 
     private PdpConnection findFreePdp() {
-        for (PdpConnection pdp : pdpList) {
-            if (pdp.getState() == PdpConnection.PdpState.INACTIVE) {
+        for (DataConnection conn : pdpList) {
+            PdpConnection pdp = (PdpConnection) conn;
+            if (pdp.getState() == DataConnection.State.INACTIVE) {
                 return pdp;
             }
         }
@@ -854,7 +754,7 @@
         return null;
     }
 
-    String getIpAddress(String apnType) {
+    protected String getIpAddress(String apnType) {
         if (mActivePdp != null
                 && (apnType == null || mActiveApn.canHandleType(apnType))) {
             return mActivePdp.getIpAddress();
@@ -870,7 +770,7 @@
         return null;
     }
 
-    String[] getDnsServers(String apnType) {
+    protected String[] getDnsServers(String apnType) {
         if (mActivePdp != null
                 && (apnType == null || mActiveApn.canHandleType(apnType))) {
             return mActivePdp.getDnsServers();
@@ -879,8 +779,7 @@
     }
 
     private boolean
-    pdpStatesHasCID (ArrayList<PDPContextState> states, int cid)
-    {
+    pdpStatesHasCID (ArrayList<PDPContextState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
             if (states.get(i).cid == cid) return true;
         }
@@ -889,10 +788,9 @@
     }
 
     private boolean
-    pdpStatesHasActiveCID (ArrayList<PDPContextState> states, int cid)
-    {
+    pdpStatesHasActiveCID (ArrayList<PDPContextState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
-            if (states.get(i).cid == cid) return states.get(i).active;
+            if (states.get(i).cid == cid) return (states.get(i).active != 0);
         }
 
         return false;
@@ -907,7 +805,7 @@
         isConnected = (state != State.IDLE && state != State.FAILED);
 
         // The "current" may no longer be valid.  MMS depends on this to send properly.
-        phone.updateCurrentCarrierInProvider();
+        ((GSMPhone) phone).updateCurrentCarrierInProvider();
 
         // TODO: It'd be nice to only do this if the changed entrie(s)
         // match the current operator.
@@ -926,9 +824,7 @@
      * via an unsolicited response (which could have happened at any
      * previous state
      */
-    private void
-    onPdpStateChanged (AsyncResult ar, boolean explicitPoll)
-    {
+    protected void onPdpStateChanged (AsyncResult ar, boolean explicitPoll) {
         ArrayList<PDPContextState> pdpStates;
 
         pdpStates = (ArrayList<PDPContextState>)(ar.result);
@@ -940,57 +836,38 @@
             return;
         }
 
+        if (state == State.CONNECTED) {
+            // The way things are supposed to work, the PDP list
+            // should not contain the CID after it disconnects.
+            // However, the way things really work, sometimes the PDP
+            // context is still listed with active = false, which
+            // makes it hard to distinguish an activating context from
+            // an activated-and-then deactivated one.
+            if (!pdpStatesHasCID(pdpStates, cidActive)) {
+                // It looks like the PDP context has deactivated.
+                // Tear everything down and try to reconnect.
 
-        // This is how things are supposed to work:
-        // The PDP list is supposed to be empty of the CID
-        // when it disconnects
+                Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
 
-        if (state == State.CONNECTED
-                && !pdpStatesHasCID(pdpStates, cidActive)) {
+                // Add an event log when the network drops PDP
+                int cid = -1;
+                GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+                if (loc != null) cid = loc.getCid();
+                EventLog.List val = new EventLog.List(cid,
+                        TelephonyManager.getDefault().getNetworkType());
+                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
 
-            // It looks like the PDP context has deactivated
-            // Tear everything down and try to reconnect
-
-            Log.i(LOG_TAG, "PDP connection has dropped. Reconnecting");
-
-            // Add an event log when the network drops PDP
-            int cid = -1;
-            GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-            if (loc != null) cid = loc.getCid();
-
-            EventLog.List val = new EventLog.List(cid,
-                    TelephonyManager.getDefault().getNetworkType());
-
-            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
-
-            cleanUpConnection(true, null);
-
-            return;
-        }
-
-        if (true) {
-            //
-            // Workaround for issue #655426
-            //
-
-            // --------------------------
-
-            // This is how some things work now: the PDP context is still
-            // listed with active = false, which makes it hard to
-            // distinguish an activating context from an activated-and-then
-            // deactivated one.
-            //
-            // Here, we only consider this authoritative if we asked for the
-            // PDP list. If it was an unsolicited response, we poll again
-            // to make sure everyone agrees on the initial state
-
-            if (state == State.CONNECTED
-                    && !pdpStatesHasActiveCID(pdpStates, cidActive)) {
+                cleanUpConnection(true, null);
+                return;
+            } else if (!pdpStatesHasActiveCID(pdpStates, cidActive)) {
+                // Here, we only consider this authoritative if we asked for the
+                // PDP list. If it was an unsolicited response, we poll again
+                // to make sure everyone agrees on the initial state.
 
                 if (!explicitPoll) {
                     // We think it disconnected but aren't sure...poll from our side
                     phone.mCM.getPDPContextList(
-                        this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+                            this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
                 } else {
                     Log.i(LOG_TAG, "PDP connection has dropped (active=false case). "
                                     + " Reconnecting");
@@ -999,10 +876,8 @@
                     int cid = -1;
                     GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
                     if (loc != null) cid = loc.getCid();
-
                     EventLog.List val = new EventLog.List(cid,
                             TelephonyManager.getDefault().getNetworkType());
-
                     EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
 
                     cleanUpConnection(true, null);
@@ -1062,9 +937,7 @@
      * with certain RIL impl's/basebands
      *
      */
-    private void
-    startPeriodicPdpPoll()
-    {
+    private void startPeriodicPdpPoll() {
         removeMessages(EVENT_POLL_PDP);
 
         sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
@@ -1074,6 +947,7 @@
         txPkts = -1;
         rxPkts = -1;
         sentSinceLastRecv = 0;
+        netStatPollPeriod = POLL_NETSTAT_MILLIS;
         mNoRecvPollCount = 0;
     }
 
@@ -1089,16 +963,14 @@
             } else {
                 mPdpResetCount = 0;
                 EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_REREGISTER_NETWORK, sentSinceLastRecv);
-                phone.mSST.reRegisterNetwork(null);
+                ((GSMPhone) phone).mSST.reRegisterNetwork(null);
             }
             // TODO: Add increasingly drastic recovery steps, eg,
             // reset the radio, reset the device.
         }
     }
 
-    private void
-    startNetStatPoll()
-    {
+    protected void startNetStatPoll() {
         if (state == State.CONNECTED && mPingTestActive == false && netStatPollEnabled == false) {
             Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
             resetPollStats();
@@ -1107,17 +979,13 @@
         }
     }
 
-    private void
-    stopNetStatPoll()
-    {
+    protected void stopNetStatPoll() {
         netStatPollEnabled = false;
         removeCallbacks(mPollNetStat);
         Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
     }
 
-    private void
-    restartRadio()
-    {
+    protected void restartRadio() {
         Log.d(LOG_TAG, "************TURN OFF RADIO**************");
         cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
         phone.mCM.setRadioPower(false, null);
@@ -1133,7 +1001,7 @@
         SystemProperties.set("net.ppp.reset-by-timeout", String.valueOf(reset+1));
     }
 
-    Runnable mPollNetStat = new Runnable()
+    private Runnable mPollNetStat = new Runnable()
     {
 
         public void run() {
@@ -1164,7 +1032,7 @@
                     newActivity = Activity.DATAINANDOUT;
                     mPdpResetCount = 0;
                 } else if (sent > 0 && received == 0) {
-                    if (phone.mCT.state == Phone.State.IDLE) {
+                    if (phone.getState() == Phone.State.IDLE) {
                         sentSinceLastRecv += sent;
                     } else {
                         sentSinceLastRecv = 0;
@@ -1188,7 +1056,8 @@
             }
 
             int watchdogTrigger = Settings.Gservices.getInt(mResolver,
-                    Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, NUMBER_SENT_PACKETS_OF_HANG);
+                    Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, 
+                    NUMBER_SENT_PACKETS_OF_HANG);
 
             if (sentSinceLastRecv >= watchdogTrigger) {
                 // we already have NUMBER_SENT_PACKETS sent without ack
@@ -1204,13 +1073,14 @@
                     // It's possible the PDP context went down and we weren't notified.
                     // Start polling the context list in an attempt to recover.
                     if (DBG) log("no DATAIN in a while; polling PDP");
-                    phone.mCM.getPDPContextList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+                    phone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
 
                     mNoRecvPollCount++;
 
                     // Slow down the poll interval to let things happen
                     netStatPollPeriod = Settings.Gservices.getInt(mResolver,
-                            Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, POLL_NETSTAT_SLOW_MILLIS);
+                            Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, 
+                            POLL_NETSTAT_SLOW_MILLIS);
                 } else {
                     if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
                                         " pkts since last received");
@@ -1242,7 +1112,7 @@
             }
         }
     };
-
+    
     private void runPingTest () {
         int status = -1;
         try {
@@ -1279,15 +1149,13 @@
      * seems like it deserves an error notification.
      * Transient errors are ignored
      */
-    private boolean
-    shouldPostNotification(PdpConnection.PdpFailCause  cause)
-    {
+    private boolean shouldPostNotification(PdpConnection.FailCause  cause) {
         boolean shouldPost = true;
         // TODO CHECK
         // if (dataLink != null) {
         //    shouldPost = dataLink.getLastLinkExitCode() != DataLink.EXIT_OPEN_FAILED;
         //}
-        return (shouldPost && cause != PdpConnection.PdpFailCause.UNKNOWN);
+        return (shouldPost && cause != PdpConnection.FailCause.UNKNOWN);
     }
 
     /**
@@ -1301,14 +1169,13 @@
         boolean retry = true;
         
         if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
-             Phone.REASON_DATA_DISABLED.equals(reason)    ||
-             Phone.REASON_PS_RESTRICT_ENABLED.equals(reason)) { 
+             Phone.REASON_DATA_DISABLED.equals(reason) ) { 
             retry = false;
         }
         return retry;
-    }
-    
-    private void reconnectAfterFail(PdpFailCause lastFailCauseCode, String reason) {
+    }   
+
+    private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
         if (state == State.FAILED) {
             Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for "
                     + (nextReconnectDelay / 1000) + "s");
@@ -1338,314 +1205,215 @@
         }
     }
 
-    private void notifyNoData(PdpConnection.PdpFailCause lastFailCauseCode) {
+    private void notifyNoData(PdpConnection.FailCause lastFailCauseCode) {
         setState(State.FAILED);
     }
 
-
-    private void log(String s) {
-        Log.d(LOG_TAG, "[DataConnectionTracker] " + s);
+    protected void onRecordsLoaded() {
+        createAllApnList();
+        if (state == State.FAILED) {
+            cleanUpConnection(false, null);
+        }
+        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
     }
 
-    //***** Overridden from Handler
-    public void
-    handleMessage (Message msg)
-    {
-        AsyncResult ar;
+    protected void onEnableNewApn() {
+        // TODO:  To support simultaneous PDP contexts, this should really only call
+        // cleanUpConnection if it needs to free up a PdpConnection.
+        cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
+    }
+
+    protected void onTrySetupData() {
+        trySetupData(null);
+    }
+
+    protected void onRestoreDefaultApn() {
+        if (DBG) Log.d(LOG_TAG, "Restore default APN");
+        setEnabled(Phone.APN_TYPE_MMS, false);
+
+        if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+            cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
+            mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+        }
+    }
+
+    protected void onRoamingOff() {
+        trySetupData(Phone.REASON_ROAMING_OFF);
+    }
+
+    protected void onRoamingOn() {
+        if (getDataOnRoamingEnabled()) {
+            trySetupData(Phone.REASON_ROAMING_ON);
+        } else {
+            if (DBG) log("Tear down data connection on roaming.");
+            cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+        }
+    }
+
+    protected void onRadioAvailable() {
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            setState(State.CONNECTED);
+            phone.notifyDataConnection(null);
+
+            Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+        }
+
+        if (state != State.IDLE) {
+            cleanUpConnection(true, null);
+        }
+    }
+
+    protected void onRadioOffOrNotAvailable() {
+        // Make sure our reconnect delay starts at the initial value
+        // next time the radio comes on
+        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+        } else {
+            if (DBG) log("Radio is off and clean up all connection");
+            // TODO: Should we reset mRequestedApnType to "default"?
+            cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+        }
+    }
+
+    protected void onDataSetupComplete(AsyncResult ar) {
         String reason = null;
+        if (ar.userObj instanceof String) {
+            reason = (String) ar.userObj;
+        }
 
-        switch (msg.what) {
-            case EVENT_RECORDS_LOADED:
-                createAllApnList();
-                if (state == State.FAILED) {
-                    cleanUpConnection(false, null);
-                }
-                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
-                break;
+        if (ar.exception == null) {
+            // everything is setup
 
-            case EVENT_ENABLE_NEW_APN:
-                // TODO:  To support simultaneous PDP contexts, this should really only call
-                // cleanUpConnection if it needs to free up a PdpConnection.
-                reason = Phone.REASON_APN_SWITCHED;
-                cleanUpConnection(true, reason);
-                break;
-
-            case EVENT_TRY_SETUP_DATA:
-                if (msg.obj instanceof String) {
-                    reason = (String)msg.obj;
-                }
-
-                trySetupData(reason);
-                break;
-
-            case EVENT_RESTORE_DEFAULT_APN:
-                if (DBG) Log.d(LOG_TAG, "Restore default APN");
-                setEnabled(Phone.APN_TYPE_MMS, false);
-                if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
-                    cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
-                    mRequestedApnType = Phone.APN_TYPE_DEFAULT;
-                }
-                break;
-
-            case EVENT_ROAMING_OFF:
-                trySetupData(Phone.REASON_ROAMING_OFF);
-                break;
-
-            case EVENT_GPRS_DETACHED:
-                onGprsDetached();
-                break;
-
-            case EVENT_GPRS_ATTACHED:
-                onGprsAttached();
-                break;
-
-            case EVENT_ROAMING_ON:
-                if (getDataOnRoamingEnabled()) {
-                    trySetupData(Phone.REASON_ROAMING_ON);
-                } else {
-                    if (DBG) log("Tear down data connection on roaming.");
-                    cleanUpConnection(true, Phone.REASON_ROAMING_ON);
-                }
-                break;
-
-            case EVENT_RADIO_AVAILABLE:
-                if (phone.getSimulatedRadioControl() != null) {
-                    // Assume data is connected on the simulator
-                    // FIXME  this can be improved
-                    setState(State.CONNECTED);
-                    phone.notifyDataConnection(null);
-
-
-                    Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
-                }
-
-                if (state != State.IDLE) {
-                    cleanUpConnection(true, null);
-                }
-            break;
-
-            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
-                // Make sure our reconnect delay starts at the initial value
-                // next time the radio comes on
-                nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
-
-                if (phone.getSimulatedRadioControl() != null) {
-                    // Assume data is connected on the simulator
-                    // FIXME  this can be improved
-                    Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
-                } else {
-                    if (DBG) log("Radio is off and clean up all connection");
-                    // TODO: Should we reset mRequestedApnType to "default"?
-                    cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
-                }
-            break;
-
-            case EVENT_DATA_SETUP_COMPLETE:
-                ar = (AsyncResult) msg.obj;
-                if (ar.userObj instanceof String) {
-                    reason = (String) ar.userObj;
-                }
-
-                if (ar.exception == null) {
-                    // everything is setup
-
-                    // arg1 contains CID for this PDP context
-                    cidActive = msg.arg1;
-                    /*
-                     * We may have switched away from the default PDP context
-                     * in order to enable a "special" APN (e.g., for MMS
-                     * traffic). Set a timer to switch back and/or disable the
-                     * special APN, so that a negligient application doesn't
-                     * permanently prevent data connectivity. What we are
-                     * protecting against here is not malicious apps, but
-                     * rather an app that inadvertantly fails to reset to the
-                     * default APN, or that dies before doing so.
-                     */
-                    if (dataEnabled[APN_MMS_ID]) {
-                        removeMessages(EVENT_RESTORE_DEFAULT_APN);
-                        sendMessageDelayed(
-                                obtainMessage(EVENT_RESTORE_DEFAULT_APN),
-                                getRestoreDefaultApnDelay());
-                    }
-                    if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
-                        SystemProperties.set("gsm.defaultpdpcontext.active", "true");
+            /*
+             * We may have switched away from the default PDP context
+             * in order to enable a "special" APN (e.g., for MMS
+             * traffic). Set a timer to switch back and/or disable the
+             * special APN, so that a negligient application doesn't
+             * permanently prevent data connectivity. What we are
+             * protecting against here is not malicious apps, but
+             * rather an app that inadvertantly fails to reset to the
+             * default APN, or that dies before doing so.
+             */
+            if (dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID]) {
+                removeMessages(EVENT_RESTORE_DEFAULT_APN);
+                sendMessageDelayed(obtainMessage(EVENT_RESTORE_DEFAULT_APN),
+                        getRestoreDefaultApnDelay());
+            }
+            if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+                SystemProperties.set("gsm.defaultpdpcontext.active", "true");
                         if (canSetPreferApn && preferredApn == null) {
                             Log.d(LOG_TAG, "PREFERED APN is null");
                             preferredApn = mActiveApn;
                             setPreferredApn(preferredApn.id);
                         }
-                    } else {
-                        SystemProperties.set("gsm.defaultpdpcontext.active", "false");
-                    }
-                    notifyDefaultData(reason);
+            } else {
+                SystemProperties.set("gsm.defaultpdpcontext.active", "false");
+            }
+            notifyDefaultData(reason);
 
-                    // TODO: For simultaneous PDP support, we need to build another
-                    // trigger another TRY_SETUP_DATA for the next APN type.  (Note
-                    // that the existing connection may service that type, in which
-                    // case we should try the next type, etc.
-                } else {
-                    PdpConnection.PdpFailCause cause;
-                    cause = (PdpConnection.PdpFailCause) (ar.result);
-                    if(DBG)
-                        log("PDP setup failed " + cause);
+            // TODO: For simultaneous PDP support, we need to build another
+            // trigger another TRY_SETUP_DATA for the next APN type.  (Note
+            // that the existing connection may service that type, in which
+            // case we should try the next type, etc.
+        } else {
+            PdpConnection.FailCause cause;
+            cause = (PdpConnection.FailCause) (ar.result);
+            if(DBG) log("PDP setup failed " + cause);
                     // Log this failure to the Event Logs.
-                    if (cause == PdpConnection.PdpFailCause.BAD_APN ||
-                        cause == PdpConnection.PdpFailCause.BAD_PAP_SECRET ||
-                        cause == PdpConnection.PdpFailCause.BARRED ||
-                        cause == PdpConnection.PdpFailCause.RADIO_ERROR_RETRY ||
-                        cause == PdpConnection.PdpFailCause.SUSPENED_TEMPORARY ||
-                        cause == PdpConnection.PdpFailCause.UNKNOWN ||
-                        cause == PdpConnection.PdpFailCause.USER_AUTHENTICATION) {
-                        int cid = -1;
-                        GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                        if (loc != null) cid = loc.getCid();
+            if (cause == PdpConnection.FailCause.BAD_APN || 
+                    cause == PdpConnection.FailCause.BAD_PAP_SECRET ||
+                    cause == PdpConnection.FailCause.BARRED ||
+                    cause == PdpConnection.FailCause.RADIO_ERROR_RETRY ||
+                    cause == PdpConnection.FailCause.SUSPENED_TEMPORARY ||
+                    cause == PdpConnection.FailCause.UNKNOWN ||
+                    cause == PdpConnection.FailCause.USER_AUTHENTICATION) {
+                int cid = -1;
+                GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+                if (loc != null) cid = loc.getCid();
 
-                        EventLog.List val = new EventLog.List(
-                            cause.ordinal(), cid,
-                            TelephonyManager.getDefault().getNetworkType());
-                        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
-                    }
-                    // No try for permanent failure
-                    if (cause.isPermanentFail()) {
-                        notifyNoData(cause);
-                    }
+                EventLog.List val = new EventLog.List(
+                        cause.ordinal(), cid, 
+                        TelephonyManager.getDefault().getNetworkType());
+                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
+            }
 
-                    if (tryNextApn(cause)) {
-                        waitingApns.remove(0);
-                        if (waitingApns.isEmpty()) {
-                            // No more to try, start delayed retry
-                            startDelayedRetry(cause, reason);
-                        } else {
-                            // we still have more apns to try
-                            setState(State.SCANNING);
-                            // Wait a bit before trying the next APN, so that 
-                            // we're not tying up the RIL command channel
-                            sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason),
-                                    RECONNECT_DELAY_INITIAL_MILLIS);
-                        }
-                    } else {
-                        startDelayedRetry(cause, reason);
-                    }
-                }
-            break;
+            // No try for permanent failure
+            if (cause.isPermanentFail()) {
+                notifyNoData(cause);
+            }
 
-            case EVENT_DISCONNECT_DONE:
-                if(DBG) log("EVENT_DISCONNECT_DONE");
-                ar = (AsyncResult) msg.obj;
-                if (ar.userObj instanceof String) {
-                    reason = (String) ar.userObj;
-                }
-                setState(State.IDLE);
-                phone.notifyDataConnection(reason);
-                mActiveApn = null;
-                if ( retryAfterDisconnected(reason) ) {
+            if (tryNextApn(cause)) {
+                waitingApns.remove(0);
+                if (waitingApns.isEmpty()) {
+                    // No more to try, start delayed retry
+                    startDelayedRetry(cause, reason);
+                } else {
+                    // we still have more apns to try
+                    setState(State.SCANNING);
                     trySetupData(reason);
                 }
-                break;
-
-            case EVENT_PDP_STATE_CHANGED:
-                ar = (AsyncResult) msg.obj;
-
-                onPdpStateChanged(ar, false);
-            break;
-
-            case EVENT_GET_PDP_LIST_COMPLETE:
-                ar = (AsyncResult) msg.obj;
-
-                onPdpStateChanged(ar, true);
-            break;
-
-            case EVENT_POLL_PDP:
-                /* See comment in startPeriodicPdpPoll */
-                ar = (AsyncResult) msg.obj;
-
-                if (!(state == State.CONNECTED)) {
-                    // not connected; don't poll anymore
-                    break;
-                }
-
-                phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
-
-                sendMessageDelayed(obtainMessage(EVENT_POLL_PDP),
-                                   POLL_PDP_MILLIS);
-            break;
-
-            case EVENT_VOICE_CALL_STARTED:
-                if (state == State.CONNECTED &&
-                        !phone.mSST.isConcurrentVoiceAndData()) {
-                    stopNetStatPoll();
-                    phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
-                }
-            break;
-
-            case EVENT_VOICE_CALL_ENDED:
-                if (state == State.CONNECTED) {
-                    if (!phone.mSST.isConcurrentVoiceAndData()) {
-                        startNetStatPoll();
-                        phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
-                    } else {
-                        // clean slate after call end.
-                        resetPollStats();
-                    }
-                } else {
-                    // in case data setup was attempted when we were on a voice call
-                    trySetupData(Phone.REASON_VOICE_CALL_ENDED);
-                }
-            break;
-
-            case EVENT_START_NETSTAT_POLL:
-                mPingTestActive = false;
-                startNetStatPoll();
-                break;
-
-            case EVENT_START_RECOVERY:
-                mPingTestActive = false;
-                doRecovery();
-                break;
-
-            case EVENT_APN_CHANGED:
-                onApnChanged();
-                break;
-            
-            case EVENT_PS_RESTRICT_ENABLED:
-                /**
-                 * We don't need to explicitly to tear down the PDP context
-                 * when PS restricted is enabled. The base band will deactive
-                 * PDP context and notify us with PDP_CONTEXT_CHANGED.
-                 * But we should stop the network polling and prevent reset PDP.
-                 */
-                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); 
-                stopNetStatPoll();
-                mIsPsRestricted = true; 
-                break;
-                
-            case EVENT_PS_RESTRICT_DISABLED:
-                /**
-                 * When PS restrict is removed, we need setup PDP connection if
-                 * PDP connection is down.
-                 */
-                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
-                mIsPsRestricted  = false;
-                if (state == State.CONNECTED) {
-                    startNetStatPoll();
-                } else {
-                    if (state == State.FAILED) {
-                        cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
-                        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
-                    }
-                    trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);
-                }
-                break;
-             
+            } else {
+                startDelayedRetry(cause, reason);
+            }
         }
     }
 
-    private boolean tryNextApn(PdpFailCause cause) {
-        return (cause != PdpFailCause.RADIO_NOT_AVIALABLE)
-            && (cause != PdpFailCause.RADIO_OFF)
-            && (cause != PdpFailCause.RADIO_ERROR_RETRY)
-            && (cause != PdpFailCause.NO_SIGNAL)
-            && (cause != PdpFailCause.SIM_LOCKED);
+    protected void onDisconnectDone(AsyncResult ar) {
+        String reason = null;
+        if(DBG) log("EVENT_DISCONNECT_DONE");
+        if (ar.userObj instanceof String) {
+           reason = (String) ar.userObj;
+        }
+        setState(State.IDLE);
+        phone.notifyDataConnection(reason);
+        mActiveApn = null;
+        if (retryAfterDisconnected(reason)) {
+            trySetupData(reason);
+        }
+    }
+
+    protected void onPollPdp() {
+        if (state == State.CONNECTED) {
+            // only poll when connected
+            phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+            sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
+        }
+    }
+
+    protected void onVoiceCallStarted() {
+        if (state == State.CONNECTED && !((GSMPhone) phone).mSST.isConcurrentVoiceAndData()) {
+            stopNetStatPoll();
+            phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
+        }
+    }
+
+    protected void onVoiceCallEnded() {
+        if (state == State.CONNECTED) {
+            if (!((GSMPhone) phone).mSST.isConcurrentVoiceAndData()) {
+                startNetStatPoll();
+                phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
+            } else {
+                // clean slate after call end.
+                resetPollStats();
+            }
+        } else {
+            // in case data setup was attempted when we were on a voice call
+            trySetupData(Phone.REASON_VOICE_CALL_ENDED);
+        }
+    }
+
+    private boolean tryNextApn(FailCause cause) {
+        return (cause != FailCause.RADIO_NOT_AVAILABLE)
+                && (cause != FailCause.RADIO_OFF)
+                && (cause != FailCause.RADIO_ERROR_RETRY)
+                && (cause != FailCause.NO_SIGNAL)
+                && (cause != FailCause.SIM_LOCKED);
     }
 
     private int getRestoreDefaultApnDelay() {
@@ -1668,7 +1436,7 @@
      */
     private void createAllApnList() {
         allApns = new ArrayList<ApnSetting>();
-        String operator = phone.mSIMRecords.getSIMOperatorNumeric();
+        String operator = ((GSMPhone) phone).mSIMRecords.getSIMOperatorNumeric();
 
         if (operator != null) {
             String selection = "numeric = '" + operator + "'";
@@ -1694,7 +1462,7 @@
         if (allApns.isEmpty()) {
             if (DBG) log("No APN found for carrier: " + operator);
             preferredApn = null;
-            notifyNoData(PdpConnection.PdpFailCause.BAD_APN);
+            notifyNoData(PdpConnection.FailCause.BAD_APN);
         } else {
             preferredApn = getPreferredApn();
             Log.d(LOG_TAG, "Get PreferredAPN");
@@ -1706,15 +1474,22 @@
     }
 
     private void createAllPdpList() {
-        pdpList = new ArrayList<PdpConnection>();
-        PdpConnection pdp;
+        pdpList = new ArrayList<DataConnection>();
+        DataConnection pdp;
 
         for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) {
-            pdp = new PdpConnection(phone);
+            pdp = new PdpConnection((GSMPhone) phone);
             pdpList.add(pdp);
          }
     }
 
+    private void destroyAllPdpList() {
+        if(pdpList != null) {
+            PdpConnection pdp;
+            pdpList.removeAll(pdpList);
+        }
+    }
+
     /**
      *
      * @return waitingApns list to be used to create PDP
@@ -1722,7 +1497,7 @@
      */
     private ArrayList<ApnSetting> buildWaitingApns() {
         ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();
-        String operator = phone.mSIMRecords.getSIMOperatorNumeric();
+        String operator = ((GSMPhone )phone).mSIMRecords.getSIMOperatorNumeric();
 
         if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
             if (canSetPreferApn && preferredApn != null) {
@@ -1775,7 +1550,7 @@
         return result.toString();
     }
 
-    private void startDelayedRetry(PdpConnection.PdpFailCause cause, String reason) {
+    private void startDelayedRetry(PdpConnection.FailCause cause, String reason) {
         notifyNoData(cause);
         if (mRequestedApnType != Phone.APN_TYPE_DEFAULT) {
             sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
@@ -1833,4 +1608,95 @@
 
         return null;
     }
+
+    public void handleMessage (Message msg) {
+
+        switch (msg.what) {
+            case EVENT_RECORDS_LOADED:
+                onRecordsLoaded();
+                break;
+
+            case EVENT_ENABLE_NEW_APN:
+                onEnableNewApn();
+                break;
+
+            case EVENT_RESTORE_DEFAULT_APN:
+                onRestoreDefaultApn();
+                break;
+
+            case EVENT_GPRS_DETACHED:
+                onGprsDetached();
+                break;
+
+            case EVENT_GPRS_ATTACHED:
+                onGprsAttached();
+                break;
+
+            case EVENT_DATA_STATE_CHANGED:
+                onPdpStateChanged((AsyncResult) msg.obj, false);
+                break;
+
+            case EVENT_GET_PDP_LIST_COMPLETE:
+                onPdpStateChanged((AsyncResult) msg.obj, true);
+                break;
+
+            case EVENT_POLL_PDP:
+                onPollPdp();
+                break;
+
+            case EVENT_START_NETSTAT_POLL:
+                mPingTestActive = false;
+                startNetStatPoll();
+                break;
+
+            case EVENT_START_RECOVERY:
+                mPingTestActive = false;
+                doRecovery();
+                break;
+
+            case EVENT_APN_CHANGED:
+                onApnChanged();
+                break;
+
+            case EVENT_PS_RESTRICT_ENABLED:
+                /**
+                 * We don't need to explicitly to tear down the PDP context
+                 * when PS restricted is enabled. The base band will deactive
+                 * PDP context and notify us with PDP_CONTEXT_CHANGED.
+                 * But we should stop the network polling and prevent reset PDP.
+                 */
+                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); 
+                stopNetStatPoll();
+                mIsPsRestricted = true; 
+                break;
+
+            case EVENT_PS_RESTRICT_DISABLED:
+                /**
+                 * When PS restrict is removed, we need setup PDP connection if
+                 * PDP connection is down.
+                 */
+                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
+                mIsPsRestricted  = false;
+                if (state == State.CONNECTED) {
+                    startNetStatPoll();
+                } else {
+                    if (state == State.FAILED) {
+                        cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
+                        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+                    }
+                    trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);
+                }
+                break;
+
+            default:
+                // handle the message in the super class DataConnectionTracker
+                super.handleMessage(msg);
+                break;
+        }
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 04f8332..4db8fc6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -18,39 +18,40 @@
 
 import android.content.Context;
 import com.android.internal.telephony.*;
+
 import android.os.*;
-import android.os.AsyncResult;
-import android.util.Log;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
+import android.telephony.PhoneNumberUtils;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
-import android.telephony.PhoneNumberUtils;
-import static com.android.internal.telephony.gsm.CommandsInterface.*;
+import android.util.Log;
+
+import static com.android.internal.telephony.CommandsInterface.*;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
 
 /**
  * The motto for this file is:
  *
- * "NOTE:	By using the # as a separator, most cases are expected to be unambiguous."
+ * "NOTE:    By using the # as a separator, most cases are expected to be unambiguous."
  *   -- TS 22.030 6.5.2
  *
  * {@hide}
  *
  */
-public final class GsmMmiCode  extends Handler implements MmiCode
-{
+public final class GsmMmiCode  extends Handler implements MmiCode {
     static final String LOG_TAG = "GSM";
 
     //***** Constants
-    
+
     // From TS 22.030 6.5.2
     static final String ACTION_ACTIVATE = "*";
     static final String ACTION_DEACTIVATE = "#";
     static final String ACTION_INTERROGATE = "*#";
     static final String ACTION_REGISTER = "**";
     static final String ACTION_ERASURE = "##";
-    
-    // Supp Service cocdes from TS 22.030 Annex B 
+
+    // Supp Service cocdes from TS 22.030 Annex B
 
     //Called line presentation
     static final String SC_CLIP    = "30";
@@ -102,25 +103,24 @@
 
     GSMPhone phone;
     Context context;
-    
+
     String action;              // One of ACTION_*
     String sc;                  // Service Code
     String sia, sib, sic;       // Service Info a,b,c
     String poundString;         // Entire MMI string up to and including #
     String dialingNumber;
     String pwd;                 // For password registration
-    
 
-    /** Set to true in processCode, not at newFromDialString time */ 
+    /** Set to true in processCode, not at newFromDialString time */
     private boolean isPendingUSSD;
 
     private boolean isUssdRequest;
 
-    State state = State.PENDING;    
+    State state = State.PENDING;
     CharSequence message;
-    
+
     //***** Class Variables
-    
+
 
     // See TS 22.030 6.5.2 "Structure of the MMI"
 
@@ -137,9 +137,9 @@
          10 = dialing number
 */
 
-    static final int MATCH_GROUP_POUND_STRING = 1; 
+    static final int MATCH_GROUP_POUND_STRING = 1;
 
-    static final int MATCH_GROUP_ACTION = 2; 
+    static final int MATCH_GROUP_ACTION = 2;
                         //(activation/interrogation/registration/erasure)
 
     static final int MATCH_GROUP_SERVICE_CODE = 3;
@@ -151,7 +151,7 @@
 
 
     //***** Public Class methods
-    
+
     /**
      * Some dial strings in GSM are defined to do non-call setup
      * things, such as modify or query supplementry service settings (eg, call
@@ -165,9 +165,8 @@
      * Please see flow chart in TS 22.030 6.5.3.2
      */
 
-    static GsmMmiCode 
-    newFromDialString(String dialString, GSMPhone phone)
-    {
+    static GsmMmiCode
+    newFromDialString(String dialString, GSMPhone phone) {
         Matcher m;
         GsmMmiCode ret = null;
 
@@ -187,7 +186,7 @@
 
         } else if (dialString.endsWith("#")) {
             // TS 22.030 sec 6.5.3.2
-            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet 
+            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
             // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
 
             ret = new GsmMmiCode(phone);
@@ -202,16 +201,15 @@
     }
 
     static GsmMmiCode
-    newNetworkInitiatedUssd (String ussdMessage, 
-                                boolean isUssdRequest, GSMPhone phone)
-    {
+    newNetworkInitiatedUssd (String ussdMessage,
+                                boolean isUssdRequest, GSMPhone phone) {
         GsmMmiCode ret;
 
         ret = new GsmMmiCode(phone);
 
         ret.message = ussdMessage;
         ret.isUssdRequest = isUssdRequest;
-        
+
         // If it's a request, set to PENDING so that it's cancelable.
         if (isUssdRequest) {
             ret.isPendingUSSD = true;
@@ -225,42 +223,39 @@
 
     static GsmMmiCode newFromUssdUserInput(String ussdMessge, GSMPhone phone) {
         GsmMmiCode ret = new GsmMmiCode(phone);
-        
+
         ret.message = ussdMessge;
         ret.state = State.PENDING;
         ret.isPendingUSSD = true;
-        
+
         return ret;
     }
 
     //***** Private Class methods
 
-    /** make empty strings be null. 
-     *  Regexp returns empty strings for empty groups 
+    /** make empty strings be null.
+     *  Regexp returns empty strings for empty groups
      */
     private static String
-    makeEmptyNull (String s)
-    {
+    makeEmptyNull (String s) {
         if (s != null && s.length() == 0) return null;
 
         return s;
     }
 
     /** returns true of the string is empty or null */
-    private static boolean 
-    isEmptyOrNull(CharSequence s)
-    {
+    private static boolean
+    isEmptyOrNull(CharSequence s) {
         return s == null || (s.length() == 0);
     }
 
 
     private static int
-    scToCallForwardReason(String sc)
-    {
-        if (sc == null) { 
+    scToCallForwardReason(String sc) {
+        if (sc == null) {
             throw new RuntimeException ("invalid call forward sc");
         }
-   
+
         if (sc.equals(SC_CF_All)) {
            return CommandsInterface.CF_REASON_ALL;
         } else if (sc.equals(SC_CFU)) {
@@ -279,8 +274,7 @@
     }
 
     private static int
-    siToServiceClass(String si)
-    {
+    siToServiceClass(String si) {
         if (si == null || si.length() == 0) {
                 return  SERVICE_CLASS_NONE;
         } else {
@@ -299,7 +293,7 @@
 /*
     Note for code 20:
      From TS 22.030 Annex C:
-                "All GPRS bearer services" are not included in "All tele and bearer services" 
+                "All GPRS bearer services" are not included in "All tele and bearer services"
                     and "All bearer services"."
 ....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
 */
@@ -319,8 +313,7 @@
     }
 
     private static int
-    siToTime (String si)
-    {
+    siToTime (String si) {
         if (si == null || si.length() == 0) {
             return 0;
         } else {
@@ -330,33 +323,30 @@
     }
 
     static boolean
-    isServiceCodeCallForwarding(String sc)
-    {
-        return sc != null && 
-                (sc.equals(SC_CFU) 
-                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy) 
-                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All) 
+    isServiceCodeCallForwarding(String sc) {
+        return sc != null &&
+                (sc.equals(SC_CFU)
+                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
+                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
                 || sc.equals(SC_CF_All_Conditional));
     }
 
     static boolean
-    isServiceCodeCallBarring(String sc)
-    {
+    isServiceCodeCallBarring(String sc) {
         return sc != null &&
-                (sc.equals(SC_BAOC) 
+                (sc.equals(SC_BAOC)
                 || sc.equals(SC_BAOIC)
                 || sc.equals(SC_BAOICxH)
                 || sc.equals(SC_BAIC)
                 || sc.equals(SC_BAICr)
                 || sc.equals(SC_BA_ALL)
                 || sc.equals(SC_BA_MO)
-                || sc.equals(SC_BA_MT));    
+                || sc.equals(SC_BA_MT));
     }
 
     static String
-    scToBarringFacility(String sc)
-    {
-        if (sc == null) { 
+    scToBarringFacility(String sc) {
+        if (sc == null) {
             throw new RuntimeException ("invalid call barring sc");
         }
 
@@ -383,11 +373,10 @@
 
     //***** Constructor
 
-    GsmMmiCode (GSMPhone phone)
-    {
+    GsmMmiCode (GSMPhone phone) {
         // The telephony unit-test cases may create GsmMmiCode's
         // in secondary threads
-        super(phone.h.getLooper());
+        super(phone.getHandler().getLooper());
         this.phone = phone;
         this.context = phone.getContext();
     }
@@ -395,21 +384,18 @@
     //***** MmiCode implementation
 
     public State
-    getState()
-    {
+    getState() {
         return state;
     }
 
     public CharSequence
-    getMessage()
-    {
+    getMessage() {
         return message;
     }
 
     // inherited javadoc suffices
     public void
-    cancel()
-    {
+    cancel() {
         // Complete or failed cannot be cancelled
         if (state == State.COMPLETE || state == State.FAILED) {
             return;
@@ -423,7 +409,7 @@
              * cancel it.
              */
             phone.mCM.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this));
-            
+
             /*
              * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice
              * from RIL.
@@ -436,7 +422,6 @@
             phone.onMMIDone (this);
         }
 
-
     }
 
     public boolean isCancelable() {
@@ -445,20 +430,17 @@
     }
 
     //***** Instance Methods
-    
 
     /** Does this dial string contain a structured or unstructured MMI code? */
     boolean
-    isMMI()
-    {
+    isMMI() {
         return poundString != null;
     }
 
     /* Is this a 1 or 2 digit "short code" as defined in TS 22.030 sec 6.5.3.2? */
     boolean
-    isShortCode()
-    {
-        return poundString == null 
+    isShortCode() {
+        return poundString == null
                     && dialingNumber != null && dialingNumber.length() <= 2;
 
     }
@@ -479,7 +461,7 @@
                           * for treating "0" and "00" as call setup strings.
                           */
                          || dialString.equals("0")
-                         || dialString.equals("00")))); 
+                         || dialString.equals("00"))));
     }
     /**
      * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
@@ -489,17 +471,16 @@
                               || sc.equals(SC_PUK) || sc.equals(SC_PUK2));
      }
 
-    /** 
+    /**
      * *See TS 22.030 Annex B
-     * In temporary mode, to suppress CLIR for a single call, enter: 
+     * In temporary mode, to suppress CLIR for a single call, enter:
      *      " * 31 # <called number> SEND "
-     *  In temporary mode, to invoke CLIR for a single call enter: 
+     *  In temporary mode, to invoke CLIR for a single call enter:
      *       " # 31 # <called number> SEND "
      */
-     
-    boolean 
-    isTemporaryModeCLIR()
-    {
+
+    boolean
+    isTemporaryModeCLIR() {
         return sc != null && sc.equals(SC_CLIR) && dialingNumber != null
                 && (isActivate() || isDeactivate());
     }
@@ -509,50 +490,43 @@
      * See also isTemporaryModeCLIR()
      */
     int
-    getCLIRMode()
-    {
+    getCLIRMode() {
         if (sc != null && sc.equals(SC_CLIR)) {
             if (isActivate()) {
                 return CommandsInterface.CLIR_SUPPRESSION;
             } else if (isDeactivate()) {
-                return CommandsInterface.CLIR_INVOCATION;            
+                return CommandsInterface.CLIR_INVOCATION;
             }
         }
-        
+
         return CommandsInterface.CLIR_DEFAULT;
     }
-    
-    boolean isActivate()
-    {
+
+    boolean isActivate() {
         return action != null && action.equals(ACTION_ACTIVATE);
     }
 
-    boolean isDeactivate()
-    {
+    boolean isDeactivate() {
         return action != null && action.equals(ACTION_DEACTIVATE);
     }
-    
-    boolean isInterrogate()
-    {
+
+    boolean isInterrogate() {
         return action != null && action.equals(ACTION_INTERROGATE);
     }
 
-    boolean isRegister()
-    {
+    boolean isRegister() {
         return action != null && action.equals(ACTION_REGISTER);
     }
 
-    boolean isErasure()
-    {
+    boolean isErasure() {
         return action != null && action.equals(ACTION_ERASURE);
     }
 
-    /** 
+    /**
      * Returns true if this is a USSD code that's been submitted to the
      * network...eg, after processCode() is called
      */
-    public boolean isPendingUSSD()
-    {
+    public boolean isPendingUSSD() {
         return isPendingUSSD;
     }
 
@@ -562,8 +536,7 @@
 
     /** Process a MMI code or short code...anything that isn't a dialing number */
     void
-    processCode ()
-    {
+    processCode () {
         try {
             if (isShortCode()) {
                 Log.d(LOG_TAG, "isShortCode");
@@ -573,7 +546,7 @@
                 // We should have no dialing numbers here
                 throw new RuntimeException ("Invalid or Unsupported MMI Code");
             } else if (sc != null && sc.equals(SC_CLIP)) {
-                Log.d(LOG_TAG, "is CLIP"); 
+                Log.d(LOG_TAG, "is CLIP");
                 if (isInterrogate()) {
                     phone.mCM.queryCLIP(
                             obtainMessage(EVENT_QUERY_COMPLETE, this));
@@ -581,7 +554,7 @@
                     throw new RuntimeException ("Invalid or Unsupported MMI Code");
                 }
             } else if (sc != null && sc.equals(SC_CLIR)) {
-                Log.d(LOG_TAG, "is CLIR"); 
+                Log.d(LOG_TAG, "is CLIR");
                 if (isActivate()) {
                     phone.mCM.setCLIR(CommandsInterface.CLIR_INVOCATION,
                         obtainMessage(EVENT_SET_COMPLETE, this));
@@ -688,13 +661,13 @@
                 // sia = basic service group
                 int serviceClass = siToServiceClass(sia);
 
-            	if (isActivate() || isDeactivate()) {
+                if (isActivate() || isDeactivate()) {
                     phone.mCM.setCallWaiting(isActivate(), serviceClass,
                             obtainMessage(EVENT_SET_COMPLETE, this));
-            	} else if (isInterrogate()) {
+                } else if (isInterrogate()) {
                     phone.mCM.queryCallWaiting(serviceClass,
                             obtainMessage(EVENT_QUERY_COMPLETE, this));
-            	} else {
+                } else {
                     throw new RuntimeException ("Invalid or Unsupported MMI Code");
                 }
             } else if (isPinCommand()) {
@@ -718,16 +691,16 @@
                     } else {
                         // pre-checks OK
                         if (sc.equals(SC_PIN)) {
-                            phone.mCM.changeSimPin(oldPinOrPuk, newPin,
+                            phone.mCM.changeIccPin(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         } else if (sc.equals(SC_PIN2)) {
-                            phone.mCM.changeSimPin2(oldPinOrPuk, newPin,
+                            phone.mCM.changeIccPin2(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         } else if (sc.equals(SC_PUK)) {
-                            phone.mCM.supplySimPuk(oldPinOrPuk, newPin,
+                            phone.mCM.supplyIccPuk(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         } else if (sc.equals(SC_PUK2)) {
-                            phone.mCM.supplySimPuk2(oldPinOrPuk, newPin,
+                            phone.mCM.supplyIccPuk2(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         }
                     }
@@ -743,7 +716,7 @@
             state = State.FAILED;
             message = context.getText(com.android.internal.R.string.mmiError);
             phone.onMMIDone(this);
-        }    
+        }
     }
 
     private void handlePasswordError(int res) {
@@ -755,8 +728,8 @@
         phone.onMMIDone(this);
     }
 
-    /** 
-     * Called from GSMPhone 
+    /**
+     * Called from GSMPhone
      *
      * An unsolicited USSD NOTIFY or REQUEST has come in matching
      * up with this pending USSD request
@@ -765,8 +738,7 @@
      *       active (ie, the network expects user input).
      */
     void
-    onUssdFinished(String ussdMessage, boolean isUssdRequest)
-    {
+    onUssdFinished(String ussdMessage, boolean isUssdRequest) {
         if (state == State.PENDING) {
             if (ussdMessage == null) {
                 message = context.getText(com.android.internal.R.string.mmiComplete);
@@ -783,15 +755,14 @@
         }
     }
 
-    /** 
-     * Called from GSMPhone 
+    /**
+     * Called from GSMPhone
      *
      * The radio has reset, and this is still pending
      */
 
     void
-    onUssdFinishedError()
-    {
+    onUssdFinishedError() {
         if (state == State.PENDING) {
             state = State.FAILED;
             message = context.getText(com.android.internal.R.string.mmiError);
@@ -808,15 +779,14 @@
         // response does not complete this MMI code...we wait for
         // an unsolicited USSD "Notify" or "Request".
         // The matching up of this is doene in GSMPhone.
-        
-        phone.mCM.sendUSSD(ussdMessage, 
+
+        phone.mCM.sendUSSD(ussdMessage,
             obtainMessage(EVENT_USSD_COMPLETE, this));
     }
 
     /** Called from GSMPhone.handleMessage; not a Handler subclass */
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
 
         switch (msg.what) {
@@ -865,13 +835,13 @@
                                             com.android.internal.R.string.mmiError);
 
                     phone.onMMIDone(this);
-                } 
+                }
 
                 // Note that unlike most everything else, the USSD complete
                 // response does not complete this MMI code...we wait for
                 // an unsolicited USSD "Notify" or "Request".
                 // The matching up of this is done in GSMPhone.
-                                
+
             break;
 
             case EVENT_USSD_CANCEL_COMPLETE:
@@ -976,8 +946,7 @@
     }
 
     private void
-    onGetClirComplete(AsyncResult ar)
-    {
+    onGetClirComplete(AsyncResult ar) {
         StringBuilder sb = new StringBuilder(getScString());
         sb.append("\n");
 
@@ -996,35 +965,35 @@
                                 com.android.internal.R.string.serviceNotProvisioned));
                     state = State.COMPLETE;
                 break;
-                    
+
                 case 1: // CLIR provisioned in permanent mode
                     sb.append(context.getText(
                                 com.android.internal.R.string.CLIRPermanent));
                     state = State.COMPLETE;
                 break;
 
-                case 2: // unknown (e.g. no network, etc.)	
+                case 2: // unknown (e.g. no network, etc.)
                     sb.append(context.getText(
                                 com.android.internal.R.string.mmiError));
                     state = State.FAILED;
                 break;
 
-                case 3: // CLIR temporary mode presentation restricted	
+                case 3: // CLIR temporary mode presentation restricted
 
                     // the 'n' parameter from TS 27.007 7.7
                     switch (clirArgs[0]) {
                         default:
                         case 0: // Default
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOnNextCallOn));
+                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
                         break;
                         case 1: // CLIR invocation
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOnNextCallOn));
+                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
                         break;
                         case 2: // CLIR suppression
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOnNextCallOff));
+                                    com.android.internal.R.string.CLIRDefaultOnNextCallOff));
                         break;
                     }
                     state = State.COMPLETE;
@@ -1036,21 +1005,21 @@
                         default:
                         case 0: // Default
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOffNextCallOff));
+                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
                         break;
                         case 1: // CLIR invocation
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOffNextCallOn));
+                                    com.android.internal.R.string.CLIRDefaultOffNextCallOn));
                         break;
                         case 2: // CLIR suppression
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOffNextCallOff));
+                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
                         break;
                     }
 
                     state = State.COMPLETE;
                 break;
-            }            
+            }
         }
 
         message = sb;
@@ -1059,23 +1028,29 @@
 
     /**
      * @param serviceClass 1 bit of the service class bit vectory
-     * @return String to be used for call forward query MMI response text. 
+     * @return String to be used for call forward query MMI response text.
      *        Returns null if unrecognized
      */
 
     private CharSequence
-    serviceClassToCFString (int serviceClass)
-    {
+    serviceClassToCFString (int serviceClass) {
         switch (serviceClass) {
-            case SERVICE_CLASS_VOICE:       return context.getText(com.android.internal.R.string.serviceClassVoice);
-            case SERVICE_CLASS_DATA:        return context.getText(com.android.internal.R.string.serviceClassData);
-            case SERVICE_CLASS_FAX:         return context.getText(com.android.internal.R.string.serviceClassFAX);
-            case SERVICE_CLASS_SMS:         return context.getText(com.android.internal.R.string.serviceClassSMS);
-            case SERVICE_CLASS_DATA_SYNC:   return context.getText(com.android.internal.R.string.serviceClassDataSync);
-            case SERVICE_CLASS_DATA_ASYNC:  return context.getText(com.android.internal.R.string.serviceClassDataAsync);
-            case SERVICE_CLASS_PACKET:      return context.getText(com.android.internal.R.string.serviceClassPacket);
-            case SERVICE_CLASS_PAD:         return context.getText(com.android.internal.R.string.serviceClassPAD);
-
+            case SERVICE_CLASS_VOICE:
+                return context.getText(com.android.internal.R.string.serviceClassVoice);
+            case SERVICE_CLASS_DATA:
+                return context.getText(com.android.internal.R.string.serviceClassData);
+            case SERVICE_CLASS_FAX:
+                return context.getText(com.android.internal.R.string.serviceClassFAX);
+            case SERVICE_CLASS_SMS:
+                return context.getText(com.android.internal.R.string.serviceClassSMS);
+            case SERVICE_CLASS_DATA_SYNC:
+                return context.getText(com.android.internal.R.string.serviceClassDataSync);
+            case SERVICE_CLASS_DATA_ASYNC:
+                return context.getText(com.android.internal.R.string.serviceClassDataAsync);
+            case SERVICE_CLASS_PACKET:
+                return context.getText(com.android.internal.R.string.serviceClassPacket);
+            case SERVICE_CLASS_PAD:
+                return context.getText(com.android.internal.R.string.serviceClassPAD);
             default:
                 return null;
         }
@@ -1084,8 +1059,7 @@
 
     /** one CallForwardInfo + serviceClassMask -> one line of text */
     private CharSequence
-    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask)
-    {
+    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask) {
         CharSequence template;
         String sources[] = {"{0}", "{1}", "{2}"};
         CharSequence destinations[] = new CharSequence[3];
@@ -1094,7 +1068,7 @@
         // CF_REASON_NO_REPLY also has a time value associated with
         // it. All others don't.
 
-        needTimeTemplate = 
+        needTimeTemplate =
             (info.reason == CommandsInterface.CF_REASON_NO_REPLY);
 
         if (info.status == 1) {
@@ -1122,8 +1096,8 @@
         }
 
         // In the template (from strings.xmls)
-        // 		{0} is one of "bearerServiceCode*" 
-        //		{1} is dialing number  
+        //         {0} is one of "bearerServiceCode*"
+        //        {1} is dialing number
         //      {2} is time in seconds
 
         destinations[0] = serviceClassToCFString(info.serviceClass & serviceClassMask);
@@ -1142,8 +1116,7 @@
 
 
     private void
-    onQueryCfComplete(AsyncResult ar)
-    {
+    onQueryCfComplete(AsyncResult ar) {
         StringBuilder sb = new StringBuilder(getScString());
         sb.append("\n");
 
@@ -1152,7 +1125,7 @@
             sb.append(context.getText(com.android.internal.R.string.mmiError));
         } else {
             CallForwardInfo infos[];
-            
+
             infos = (CallForwardInfo[]) ar.result;
 
             if (infos.length == 0) {
@@ -1166,18 +1139,18 @@
                 SpannableStringBuilder tb = new SpannableStringBuilder();
 
                 // Each bit in the service class gets its own result line
-                // The service classes may be split up over multiple 
+                // The service classes may be split up over multiple
                 // CallForwardInfos. So, for each service classs, find out
                 // which CallForwardInfo represents it and then build
                 // the response text based on that
 
-                for (int serviceClassMask = 1 
+                for (int serviceClassMask = 1
                             ; serviceClassMask <= SERVICE_CLASS_MAX
-                            ; serviceClassMask <<= 1 
+                            ; serviceClassMask <<= 1
                 ) {
                     for (int i = 0, s = infos.length; i < s ; i++) {
                         if ((serviceClassMask & infos[i].serviceClass) != 0) {
-                            tb.append(makeCFQueryResultMessage(infos[i], 
+                            tb.append(makeCFQueryResultMessage(infos[i],
                                             serviceClassMask));
                             tb.append("\n");
                         }
@@ -1191,12 +1164,11 @@
 
         message = sb;
         phone.onMMIDone(this);
-    
+
     }
 
     private void
-    onQueryComplete(AsyncResult ar)
-    {
+    onQueryComplete(AsyncResult ar) {
         StringBuilder sb = new StringBuilder(getScString());
         sb.append("\n");
 
@@ -1230,15 +1202,15 @@
         message = sb;
         phone.onMMIDone(this);
     }
-    
-    private CharSequence
-    createQueryCallWaitingResultMessage(int serviceClass)
-    {
-        StringBuilder sb = new StringBuilder(context.getText(com.android.internal.R.string.serviceEnabledFor));
 
-        for (int classMask = 1 
+    private CharSequence
+    createQueryCallWaitingResultMessage(int serviceClass) {
+        StringBuilder sb =
+                new StringBuilder(context.getText(com.android.internal.R.string.serviceEnabledFor));
+
+        for (int classMask = 1
                     ; classMask <= SERVICE_CLASS_MAX
-                    ; classMask <<= 1 
+                    ; classMask <<= 1
         ) {
             if ((classMask & serviceClass) != 0) {
                 sb.append("\n");
@@ -1267,8 +1239,8 @@
     /***
      * TODO: It would be nice to have a method here that can take in a dialstring and
      * figure out if there is an MMI code embedded within it.  This code would replace
-     * some of the string parsing functionality in the Phone App's 
-     * SpecialCharSequenceMgr class.   
+     * some of the string parsing functionality in the Phone App's
+     * SpecialCharSequenceMgr class.
      */
 
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
new file mode 100644
index 0000000..3e73caf
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Intent;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.telephony.ServiceState;
+import android.util.Config;
+import android.util.Log;
+
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.telephony.SMSDispatcher;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+
+final class GsmSMSDispatcher extends SMSDispatcher {
+    private static final String TAG = "GSM";
+
+    GsmSMSDispatcher(GSMPhone phone) {
+        super(phone);
+    }
+
+    /**
+     * Called when a status report is received.  This should correspond to
+     * a previously successful SEND.
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           be a String representing the status report PDU, as ASCII hex.
+     */
+    protected void handleStatusReport(AsyncResult ar) {
+        String pduString = (String) ar.result;
+        SmsMessage sms = SmsMessage.newFromCDS(pduString);
+
+        if (sms != null) {
+            int messageRef = sms.messageRef;
+            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
+                SmsTracker tracker = deliveryPendingList.get(i);
+                if (tracker.mMessageRef == messageRef) {
+                    // Found it.  Remove from list and broadcast.
+                    deliveryPendingList.remove(i);
+                    PendingIntent intent = tracker.mDeliveryIntent;
+                    Intent fillIn = new Intent();
+                    fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
+                    try {
+                        intent.send(mContext, Activity.RESULT_OK, fillIn);
+                    } catch (CanceledException ex) {}
+
+                    // Only expect to see one tracker matching this messageref
+                    break;
+                }
+            }
+        }
+
+        if (mCm != null) {
+            mCm.acknowledgeLastIncomingSMS(true, null);
+        }
+    }
+
+
+    /**
+     * Dispatches an incoming SMS messages.
+     *
+     * @param sms the incoming message from the phone
+     */
+    protected void dispatchMessage(SmsMessageBase smsb) {
+
+        // If sms is null, means there was a parsing error.
+        // TODO: Should NAK this.
+        if (smsb == null) {
+            return;
+        }
+        SmsMessage sms = (SmsMessage) smsb;
+        boolean handled = false;
+
+        // Special case the message waiting indicator messages
+        if (sms.isMWISetMessage()) {
+            ((GSMPhone) mPhone).updateMessageWaitingIndicator(true);
+
+            if (sms.isMwiDontStore()) {
+                handled = true;
+            }
+
+            if (Config.LOGD) {
+                Log.d(TAG,
+                        "Received voice mail indicator set SMS shouldStore="
+                         + !handled);
+            }
+        } else if (sms.isMWIClearMessage()) {
+            ((GSMPhone) mPhone).updateMessageWaitingIndicator(false);
+
+            if (sms.isMwiDontStore()) {
+                handled = true;
+            }
+
+            if (Config.LOGD) {
+                Log.d(TAG,
+                        "Received voice mail indicator clear SMS shouldStore="
+                        + !handled);
+            }
+        }
+
+        if (handled) {
+            return;
+        }
+
+        // Parse the headers to see if this is partial, or port addressed
+        int referenceNumber = -1;
+        int count = 0;
+        int sequence = 0;
+        int destPort = -1;
+
+        SmsHeader header = sms.getUserDataHeader();
+        if (header != null) {
+            for (SmsHeader.Element element : header.getElements()) {
+                try {
+                    switch (element.getID()) {
+                        case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = data[0] & 0xff;
+                            count = data[1] & 0xff;
+                            sequence = data[2] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
+                            count = data[2] & 0xff;
+                            sequence = data[3] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
+                            byte[] data = element.getData();
+                            
+                            destPort = (data[0] & 0xff) << 8;
+                            destPort |= (data[1] & 0xff);
+                            
+                            break;
+                        }
+                    }
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    Log.e(TAG, "Bad element in header", e);
+                    return;  // TODO: NACK the message or something, don't just discard.
+                }
+            }
+        }
+
+        if (referenceNumber == -1) {
+            // notify everyone of the message if it isn't partial
+            byte[][] pdus = new byte[1][];
+            pdus[0] = sms.getPdu();
+
+            if (destPort != -1) {
+                if (destPort == SmsHeader.PORT_WAP_PUSH) {
+                    mWapPush.dispatchWapPdu(sms.getUserData());
+                }
+                // The message was sent to a port, so concoct a URI for it
+                dispatchPortAddressedPdus(pdus, destPort);
+            } else {
+                // It's a normal message, dispatch it
+                dispatchPdus(pdus);
+            }
+        } else {
+            // Process the message part
+            processMessagePart(sms, referenceNumber, sequence, count, destPort);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void sendMultipartText(String destinationAddress, String scAddress,
+            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
+            ArrayList<PendingIntent> deliveryIntents) {
+        int ref = ++sConcatenatedRef & 0xff;
+
+        for (int i = 0, count = parts.size(); i < count; i++) {
+            // build SmsHeader
+            byte[] data = new byte[3];
+            data[0] = (byte) ref;   // reference #, unique per message
+            data[1] = (byte) count; // total part count
+            data[2] = (byte) (i + 1);  // 1-based sequence
+            SmsHeader header = new SmsHeader();
+            header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
+            PendingIntent sentIntent = null;
+            PendingIntent deliveryIntent = null;
+
+            if (sentIntents != null && sentIntents.size() > i) {
+                sentIntent = sentIntents.get(i);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > i) {
+                deliveryIntent = deliveryIntents.get(i);
+            }
+
+            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
+                    parts.get(i), deliveryIntent != null, header.toByteArray());
+
+            sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+        }
+    }
+
+    /**
+     * Send a multi-part text based SMS which already passed SMS control check.
+     *
+     * It is the working function for sendMultipartText().
+     * 
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     */
+    private void sendMultipartTextWithPermit(String destinationAddress, 
+            String scAddress, ArrayList<String> parts,
+            ArrayList<PendingIntent> sentIntents, 
+            ArrayList<PendingIntent> deliveryIntents) {
+        
+        PendingIntent sentIntent = null;
+        PendingIntent deliveryIntent = null;
+        
+        // check if in service
+        int ss = mPhone.getServiceState().getState();
+        if (ss != ServiceState.STATE_IN_SERVICE) {
+            for (int i = 0, count = parts.size(); i < count; i++) {
+                if (sentIntents != null && sentIntents.size() > i) {
+                    sentIntent = sentIntents.get(i);
+                }
+                SmsTracker tracker = SmsTrackerFactory(null, sentIntent, null);
+                handleNotInService(ss, tracker);
+            }
+            return;
+        }
+
+        int ref = ++sConcatenatedRef & 0xff;
+
+        for (int i = 0, count = parts.size(); i < count; i++) {
+            // build SmsHeader
+            byte[] data = new byte[3];
+            data[0] = (byte) ref;   // reference #, unique per message
+            data[1] = (byte) count; // total part count
+            data[2] = (byte) (i + 1);  // 1-based sequence
+            SmsHeader header = new SmsHeader();
+            header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
+ 
+            if (sentIntents != null && sentIntents.size() > i) {
+                sentIntent = sentIntents.get(i);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > i) {
+                deliveryIntent = deliveryIntents.get(i);
+            }
+
+            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
+                    parts.get(i), deliveryIntent != null, header.toByteArray());
+
+            HashMap<String, Object> map = new HashMap<String, Object>();
+            map.put("smsc", pdus.encodedScAddress);
+            map.put("pdu", pdus.encodedMessage);
+
+            SmsTracker tracker =  SmsTrackerFactory(map, sentIntent, deliveryIntent);
+            sendSms(tracker);
+        }        
+    }
+
+    /** {@inheritDoc} */
+    protected void sendSms(SmsTracker tracker) {
+        HashMap map = tracker.mData;
+
+        byte smsc[] = (byte[]) map.get("smsc");
+        byte pdu[] = (byte[]) map.get("pdu");
+
+        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
+        mCm.sendSMS(IccUtils.bytesToHexString(smsc),
+                IccUtils.bytesToHexString(pdu), reply);
+    }
+
+    /**
+     * Send the multi-part SMS based on multipart Sms tracker
+     * 
+     * @param tracker holds the multipart Sms tracker ready to be sent
+     */
+    protected void sendMultipartSms (SmsTracker tracker) {
+        ArrayList<String> parts;
+        ArrayList<PendingIntent> sentIntents;
+        ArrayList<PendingIntent> deliveryIntents;
+        
+        HashMap map = tracker.mData;
+        
+        String destinationAddress = (String) map.get("destination");
+        String scAddress = (String) map.get("scaddress");
+        
+        parts = (ArrayList<String>) map.get("parts");
+        sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents");
+        deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents");
+     
+        sendMultipartTextWithPermit(destinationAddress, 
+                scAddress, parts, sentIntents, deliveryIntents);
+
+    }
+
+    /** {@inheritDoc} */
+    protected void acknowledgeLastIncomingSms(boolean success, Message response){
+        // FIXME unit test leaves cm == null. this should change
+        if (mCm != null) {
+            mCm.acknowledgeLastIncomingSMS(success, response);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void activateCellBroadcastSms(int activate, Message response) {
+        // Unless CBS is implemented for GSM, this point should be unreachable.
+        Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
+        response.recycle();
+    }
+
+    /** {@inheritDoc} */
+    protected void getCellBroadcastSmsConfig(Message response){
+        // Unless CBS is implemented for GSM, this point should be unreachable.
+        Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
+        response.recycle();
+    }
+
+    /** {@inheritDoc} */
+    protected  void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+        // Unless CBS is implemented for GSM, this point should be unreachable.
+        Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
+        response.recycle();
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
similarity index 87%
rename from telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index e336d7d..9ab1002 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,19 +16,7 @@
 
 package com.android.internal.telephony.gsm;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC;
-
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.DataConnectionTracker.State;
-
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -49,13 +37,32 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Telephony.Intents;
-import android.telephony.gsm.GsmCellLocation;
 import android.telephony.ServiceState;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 import android.util.Config;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.TimeUtils;
-import android.util.EventLog;
+
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.TelephonyIntents;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
 
 import java.util.Arrays;
 import java.util.Calendar;
@@ -65,30 +72,9 @@
 /**
  * {@hide}
  */
-final class ServiceStateTracker extends Handler
-{
-    /**
-     *  The access technology currently in use:
-     *  0 = unknown
-     *  1 = GPRS only
-     *  2 = EDGE
-     *  3 = UMTS
-     */
-    static final int DATA_ACCESS_UNKNOWN = 0;
-    static final int DATA_ACCESS_GPRS = 1;
-    static final int DATA_ACCESS_EDGE = 2;
-    static final int DATA_ACCESS_UMTS = 3;
-    
-    static final int MAX_NUM_DATA_STATE_READS = 15;
-    static final int DATA_STATE_POLL_SLEEP_MS = 100;
-
+final class GsmServiceStateTracker extends ServiceStateTracker {
     //***** Instance Variables
-
     GSMPhone phone;
-    CommandsInterface cm;
-
-    ServiceState ss;
-    ServiceState newSS;
     GsmCellLocation cellLoc;
     GsmCellLocation newCellLoc;
     int mPreferredNetworkType;
@@ -97,18 +83,6 @@
     int rssi = 99;     // signal strength 0-31, 99=unknown
                        // That's "received signal strength indication" fyi
 
-    int[] pollingContext;  // Used as a unique identifier to
-                            // track requests associated with a poll
-                            // and ignore stale responses.
-                            // The value is a count-down of expected responses
-                            // in this pollingContext
-
-    boolean mDesiredPowerState;
-
-    boolean dontPollSignalStrength = false; // Default is to poll strength
-        // If we're getting unsolicited signal strength updates from the radio,
-        // set value to true and don't bother polling any more
-
     private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
     private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
 
@@ -120,14 +94,10 @@
     /* gsm roaming status solely based on TS 27.007 7.2 CREG */
     private boolean mGsmRoaming = false;
 
-    private RegistrantList networkAttachedRegistrants = new RegistrantList();
     private RegistrantList gprsAttachedRegistrants = new RegistrantList();
     private RegistrantList gprsDetachedRegistrants = new RegistrantList();
-    private RegistrantList roamingOnRegistrants = new RegistrantList();
-    private RegistrantList roamingOffRegistrants = new RegistrantList();
     private RegistrantList psRestrictEnabledRegistrants = new RegistrantList();
     private RegistrantList psRestrictDisabledRegistrants = new RegistrantList();
-    
 
     // Sometimes we get the NITZ time before we know what country we are in.
     // Keep the time zone information from the NITZ string so we can fix
@@ -137,6 +107,7 @@
     private boolean mZoneDst;
     private long mZoneTime;
     private boolean mGotCountryCode = false;
+    private ContentResolver cr;
 
     String mSavedTimeZone;
     long mSavedTime;
@@ -170,13 +141,10 @@
     static final boolean DBG = true;
     static final String LOG_TAG = "GSM";
 
-    // signal strength poll rate
-    static final int POLL_PERIOD_MILLIS = 20 * 1000;
-
     // waiting period before recheck gprs and voice registration
     static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
 
-    // restricted state type
+    // notification type
     static final int PS_ENABLED = 1001;             // Access Control blocks data service
     static final int PS_DISABLED = 1002;            // Access Control enables data service
     static final int CS_ENABLED = 1003;             // Access Control blocks all voice/sms service
@@ -187,72 +155,21 @@
     // notification id
     static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted 
     static final int CS_NOTIFICATION = 999; //id to update and cancel CS restricted
-    
-    //***** Events
-    static final int EVENT_RADIO_STATE_CHANGED       = 1;
-    static final int EVENT_NETWORK_STATE_CHANGED        = 2;
-    static final int EVENT_GET_SIGNAL_STRENGTH  = 3;
-    static final int EVENT_POLL_STATE_REGISTRATION = 4;
-    static final int EVENT_POLL_STATE_GPRS = 5;
-    static final int EVENT_POLL_STATE_OPERATOR         = 6;
-    static final int EVENT_POLL_SIGNAL_STRENGTH = 10;
-    static final int EVENT_NITZ_TIME = 11;
-    static final int EVENT_SIGNAL_STRENGTH_UPDATE = 12;
-    static final int EVENT_RADIO_AVAILABLE = 13;
-    static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14;
-    static final int EVENT_GET_LOC_DONE = 15;
-    static final int EVENT_SIM_RECORDS_LOADED = 16;
-    static final int EVENT_SIM_READY = 17;
-    static final int EVENT_LOCATION_UPDATES_ENABLED = 18;
-    static final int EVENT_GET_PREFERRED_NETWORK_TYPE = 19;
-    static final int EVENT_SET_PREFERRED_NETWORK_TYPE = 20;
-    static final int EVENT_RESET_PREFERRED_NETWORK_TYPE = 21;
-    static final int EVENT_CHECK_REPORT_GPRS = 22;
-    static final int EVENT_RESTRICTED_STATE_CHANGED = 23;
-
-  //***** Time Zones
-
-    private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
-
-    // List of ISO codes for countries that can have an offset of GMT+0
-    // when not in daylight savings time.  This ignores some small places
-    // such as the Canary Islands (Spain) and Danmarkshavn (Denmark).
-    // The list must be sorted by code.
-    private static final String[] GMT_COUNTRY_CODES = {
-        "bf", // Burkina Faso
-        "ci", // Cote d'Ivoire
-        "eh", // Western Sahara
-        "fo", // Faroe Islands, Denmark
-        "gh", // Ghana
-        "gm", // Gambia
-        "gn", // Guinea
-        "gw", // Guinea Bissau
-        "ie", // Ireland
-        "lr", // Liberia
-        "is", // Iceland
-        "ma", // Morocco
-        "ml", // Mali
-        "mr", // Mauritania
-        "pt", // Portugal
-        "sl", // Sierra Leone
-        "sn", // Senegal
-        "st", // Sao Tome and Principe
-        "tg", // Togo
-        "uk", // U.K
-    };
 
     private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
         @Override
         public void onChange(boolean selfChange) {
-            Log.i("ServiceStateTracker", "Auto time state changed");
+            Log.i("GsmServiceStateTracker", "Auto time state changed");
             revertToNitz();
         }
     };
-    
+
+
     //***** Constructors
 
-    ServiceStateTracker(GSMPhone phone)
-    {
+    public GsmServiceStateTracker(GSMPhone phone) {
+        super();
+
         this.phone = phone;
         cm = phone.mCM;
         ss = new ServiceState();
@@ -265,13 +182,13 @@
                 (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
 
-        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);        
+        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
 
         cm.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
         cm.setOnNITZTime(this, EVENT_NITZ_TIME, null);
         cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
-        cm.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);       
+        cm.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);
         cm.registerForSIMReady(this, EVENT_SIM_READY, null);
 
         // system setting property AIRPLANE_MODE_ON is set in Settings.
@@ -280,7 +197,7 @@
                 Settings.System.AIRPLANE_MODE_ON, 0);
         mDesiredPowerState = ! (airplaneMode > 0);
 
-        ContentResolver cr = phone.getContext().getContentResolver();
+        cr = phone.getContext().getContentResolver();
         cr.registerContentObserver(
                 Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
                 mAutoTimeObserver);
@@ -288,6 +205,24 @@
         mNeedToRegForSimLoaded = true;
     }
 
+    public void dispose() {
+        //Unregister for all events
+        cm.unregisterForAvailable(this);
+        cm.unregisterForRadioStateChanged(this);
+        cm.unregisterForNetworkStateChanged(this);
+        cm.unregisterForSIMReady(this);
+
+        phone.mSIMRecords.unregisterForRecordsLoaded(this);
+        cm.unSetOnSignalStrengthUpdate(this);
+        cm.unSetOnRestrictedStateChanged(this);
+        cm.unSetOnNITZTime(this);
+        cr.unregisterContentObserver(this.mAutoTimeObserver);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized");
+    }
+
     /**
      * Registration point for transition into GPRS attached.
      * @param h handler to notify
@@ -303,7 +238,11 @@
         }
     }
 
-    void registerForNetworkAttach(Handler h, int what, Object obj) {
+    /*protected*/ void unregisterForGprsAttached(Handler h) {
+        gprsAttachedRegistrants.remove(h);
+    }
+
+    /*protected*/  void registerForNetworkAttach(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         networkAttachedRegistrants.add(r);
 
@@ -311,6 +250,10 @@
             r.notifyRegistrant();
         }
     }
+
+    /*protected*/  void unregisterForNetworkAttach(Handler h) {
+        networkAttachedRegistrants.remove(h);
+    }
     /**
      * Registration point for transition into GPRS detached.
      * @param h handler to notify
@@ -326,52 +269,8 @@
         }
     }
 
-    /**
-     * Registration point for combined roaming on
-     * combined roaming is true when roaming is true and ONS differs SPN
-     *
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForRoamingOn(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        roamingOnRegistrants.add(r);
-
-        if (ss.getRoaming()) {
-            r.notifyRegistrant();
-        }
-    }
-
-    /**
-     * Registration point for combined roaming off
-     * combined roaming is true when roaming is true and ONS differs SPN
-     *
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForRoamingOff(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        roamingOffRegistrants.add(r);
-
-        if (!ss.getRoaming()) {
-            r.notifyRegistrant();
-        }
-    }
-
-    /**
-     * Reregister network through toggle perferred network type
-     * This is a work aorund to deregister and register network since there is
-     * no ril api to set COPS=2 (deregister) only.
-     *
-     * @param onComplete is dispatched when this is complete.  it will be
-     * an AsyncResult, and onComplete.obj.exception will be non-null
-     * on failure.
-     */
-    void reRegisterNetwork(Message onComplete) {
-        cm.getPreferredNetworkType(
-                obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
+    /*protected*/  void unregisterForGprsDetached(Handler h) {
+        gprsDetachedRegistrants.remove(h);
     }
 
     /**
@@ -380,7 +279,7 @@
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
+    /*protected*/  void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
         Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled "); 
         Registrant r = new Registrant(h, what, obj);
         psRestrictEnabledRegistrants.add(r);
@@ -389,14 +288,18 @@
             r.notifyRegistrant();
         }
     }
-    
+
+    /*protected*/  void unregisterForPsRestrictedEnabled(Handler h) {
+        psRestrictEnabledRegistrants.remove(h);
+    }
+
     /**
      * Registration point for transition out of packet service restricted zone.
      * @param h handler to notify
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
+    /*protected*/  void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
         Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled "); 
         Registrant r = new Registrant(h, what, obj);
         psRestrictDisabledRegistrants.add(r);
@@ -406,34 +309,21 @@
         }
     }
     
-    //***** Called from GSMPhone
-
-    public void
-    setRadioPower(boolean power)
-    {
-        mDesiredPowerState = power;
-
-        setPowerStateToDesired();
+    /*protected*/  void unregisterForPsRestrictedDisabled(Handler h) {
+        psRestrictDisabledRegistrants.remove(h);
     }
 
+    //***** Called from GSMPhone
     public void
     getLacAndCid(Message onComplete) {
         cm.getRegistrationState(obtainMessage(
                         EVENT_GET_LOC_DONE, onComplete));
     }
 
-    /*package*/ void enableLocationUpdates() {
-        cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
-    }
 
-    /*package*/ void disableLocationUpdates() {
-        cm.setLocationUpdates(false, null);
-    }
-    //***** Overridden from Handler
-
+    //***** Overridden from ServiceStateTracker
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
         int[] ints;
         String[] strings;
@@ -476,8 +366,8 @@
                 // This callback is called when signal strength is polled
                 // all by itself
 
-                if (!(cm.getRadioState().isOn())) {
-                    // Polling will continue when radio turns back on
+                if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isCdma())) {
+                    // Polling will continue when radio turns back on and not CDMA
                     return;
                 }
                 ar = (AsyncResult) msg.obj;
@@ -493,7 +383,7 @@
                     String states[] = (String[])ar.result;
                     int lac = -1;
                     int cid = -1;
-                    if (states.length == 3) {
+                    if (states.length >= 3) {
                         try {
                             if (states[1] != null && states[1].length() > 0) {
                                 lac = Integer.parseInt(states[1], 16);
@@ -591,13 +481,11 @@
                 if (ar.exception == null) {
                     mPreferredNetworkType = ((int[])ar.result)[0];
                 } else {
-                    mPreferredNetworkType = Phone.NT_AUTO_TYPE;
+                    mPreferredNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
                 }
 
                 message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj);
-                int toggledNetworkType =
-                        (mPreferredNetworkType == Phone.NT_AUTO_TYPE) ?
-                        Phone.NT_GSM_TYPE : Phone.NT_AUTO_TYPE;
+                int toggledNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
 
                 cm.setPreferredNetworkType(toggledNetworkType, message);
                 break;
@@ -630,12 +518,47 @@
                 onRestrictedStateChanged(ar);
                 break;
 
+            default:
+                Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+            break;
         }
     }
 
     //***** Private Instance Methods
 
-    private void updateSpnDisplay() {
+    protected void setPowerStateToDesired()
+    {
+        // If we want it on and it's off, turn it on
+        if (mDesiredPowerState
+            && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
+            cm.setRadioPower(true, null);
+        } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
+            DataConnectionTracker dcTracker = phone.mDataConnection;
+            if (! dcTracker.isDataConnectionAsDesired()) {
+
+                EventLog.List val = new EventLog.List(
+                        dcTracker.getStateInString(),
+                        (dcTracker.getAnyDataEnabled() ? 1 : 0) );
+                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
+            }
+            dcTracker.cleanConnectionBeforeRadioOff();
+            
+            // poll data state up to 15 times, with a 100ms delay
+            // totaling 1.5 sec. Normal data disable action will finish in 100ms.
+            for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
+                if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED 
+                        && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
+                    Log.d(LOG_TAG, "Data shutdown complete.");
+                    break;
+                }
+                SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
+            }
+            // If it's on and available and we want it off..
+            cm.setRadioPower(false, null);
+        } // Otherwise, we're in the desired state
+    }
+    
+    protected void updateSpnDisplay() {
         int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric());
         String spn = phone.mSIMRecords.getServiceProviderName();
         String plmn = ss.getOperatorAlphaLong();
@@ -659,55 +582,12 @@
         curPlmn = plmn;
     }
 
-    private void
-    setPowerStateToDesired()
-    {
-        // If we want it on and it's off, turn it on
-        if (mDesiredPowerState
-            && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF
-        ) {
-            cm.setRadioPower(true, null);
-        } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
-            DataConnectionTracker dcTracker = phone.mDataConnection;
-            if (! dcTracker.isDataConnectionAsDesired()) {
-
-                EventLog.List val = new EventLog.List(
-                        dcTracker.getStateInString(),
-                        (dcTracker.getAnyDataEnabled() ? 1 : 0) );
-                EventLog.writeEvent(TelephonyEventLog.EVENT_DATA_STATE_RADIO_OFF, val);
-            }
-            dcTracker.cleanConnectionBeforeRadioOff();
-            
-            // poll data state up to 15 times, with a 100ms delay
-            // totaling 1.5 sec. Normal data disable action will finish in 100ms.
-            for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
-                if (dcTracker.state != State.CONNECTED 
-                        && dcTracker.state != State.DISCONNECTING) {
-                    Log.d(LOG_TAG, "Data shutdown complete.");
-                    break;
-                }
-                SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
-            }
-            // If it's on and available and we want it off..
-            cm.setRadioPower(false, null);
-        } // Otherwise, we're in the desired state
-    }
-
-    /** Cancel a pending (if any) pollState() operation */
-    private void
-    cancelPollState()
-    {
-        // This will effectively cancel the rest of the poll requests
-        pollingContext = new int[1];
-    }
-
     /**
      * Handle the result of one of the pollState()-related requests
      */
 
-    private void
-    handlePollStateResult (int what, AsyncResult ar)
-    {
+    protected void
+    handlePollStateResult (int what, AsyncResult ar) {
         int ints[];
         String states[];
 
@@ -749,7 +629,7 @@
                     if (states.length > 0) {
                         try {
                             regState = Integer.parseInt(states[0]);
-                            if (states.length == 3) {
+                            if (states.length >= 3) {
                                 if (states[1] != null && states[1].length() > 0) {
                                     lac = Integer.parseInt(states[1], 16);
                                 }
@@ -820,8 +700,7 @@
     }
 
     private void
-    setRssiDefaultValues()
-    {
+    setRssiDefaultValues() {
         rssi = 99;
     }
 
@@ -835,8 +714,7 @@
      */
 
     private void
-    pollState()
-    {
+    pollState() {
         pollingContext = new int[1];
         pollingContext[0] = 0;
 
@@ -850,7 +728,6 @@
                 pollStateDone();
             break;
 
-
             case RADIO_OFF:
                 newSS.setStateOff();
                 newCellLoc.setStateInvalid();
@@ -860,6 +737,20 @@
                 pollStateDone();
             break;
 
+            case RUIM_NOT_READY:
+            case RUIM_READY:
+            case RUIM_LOCKED_OR_ABSENT:
+            case NV_NOT_READY:
+            case NV_READY:
+                Log.d(LOG_TAG, "Radio Technology Change ongoing, setting SS to off");
+                newSS.setStateOff();
+                newCellLoc.setStateInvalid();
+                setRssiDefaultValues();
+                mGotCountryCode = false;
+
+                pollStateDone();
+                break;
+
             default:
                 // Issue all poll-related commands at once
                 // then count down the responses, which
@@ -889,6 +780,7 @@
     }
 
     private static String networkTypeToString(int type) {
+        //Network Type from GPRS_REGISTRATION_STATE
         String ret = "unknown";
 
         switch (type) {
@@ -901,14 +793,16 @@
             case DATA_ACCESS_UMTS:
                 ret = "UMTS";
                 break;
+            default:
+                Log.e(LOG_TAG, "Wrong network type: " + Integer.toString(type));
+                break;
         }
 
         return ret;
     }
 
     private void
-    pollStateDone()
-    {
+    pollStateDone() {
         if (DBG) {
             Log.d(LOG_TAG, "Poll ServiceState done: " +
                 " oldSS=[" + ss + "] newSS=[" + newSS +
@@ -1131,9 +1025,8 @@
     }
 
     private void
-    queueNextSignalStrengthPoll()
-    {
-        if (dontPollSignalStrength) {
+    queueNextSignalStrengthPoll() {
+        if (dontPollSignalStrength || (cm.getRadioState().isCdma())) {
             // The radio is telling us about signal strength changes
             // we don't have to ask it
             return;
@@ -1155,8 +1048,7 @@
      *  Called both for solicited and unsolicited signal stength updates
      */
     private void
-    onSignalStrengthResult(AsyncResult ar)
-    {
+    onSignalStrengthResult(AsyncResult ar) {
         int oldRSSI = rssi;
 
         if (ar.exception != null) {
@@ -1176,15 +1068,21 @@
         }
 
         if (rssi != oldRSSI) {
-            phone.notifySignalStrength();
+            try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
+                  // POLL_PERIOD_MILLIS) during Radio Technology Change)
+                phone.notifySignalStrength();
+           } catch (NullPointerException ex) {
+                Log.d(LOG_TAG, "onSignalStrengthResult() Phone already destroyed: " + ex 
+                        + "Signal Stranth not notified");
+           }
         }
     }
-    
+
     /**
      * Set restricted state based on the OnRestrictedStateChanged notification
      * If any voice or packet restricted state changes, trigger a UI
      * notification and notify registrants when sim is ready.
-     * 
+     *
      * @param ar an int value of RIL_RESTRICTED_STATE_*
      */
     private void onRestrictedStateChanged(AsyncResult ar)
@@ -1201,10 +1099,8 @@
             newRs.setCsEmergencyRestricted(
                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
-            
-
             //ignore the normal call and data restricted state before SIM READY
-            if (phone.getSimCard().getState() == SimCard.State.READY){ 
+            if (phone.getIccCard().getState() == IccCard.State.READY) { 
                 newRs.setCsNormalRestricted(
                         ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
                         ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
@@ -1272,7 +1168,7 @@
                     setNotification(CS_NORMAL_ENABLED); 
                 }
             }
-            
+
             rs = newRs;
         }
         Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs);
@@ -1280,8 +1176,7 @@
 
     /** code is registration state 0-5 from TS 27.007 7.2 */
     private int
-    regCodeToServiceState(int code)
-    {
+    regCodeToServiceState(int code) {
         switch (code) {
             case 0:
             case 2: // 2 is "searching"
@@ -1308,8 +1203,7 @@
      * returns true if registered roam, false otherwise
      */
     private boolean
-    regCodeIsRoaming (int code)
-    {
+    regCodeIsRoaming (int code) {
         // 5 is  "in service -- roam"
         return 5 == code;
     }
@@ -1323,7 +1217,7 @@
      */
     private
     boolean isRoamingBetweenOperators(boolean gsmRoaming, ServiceState s) {
-        String spn = SystemProperties.get(PROPERTY_SIM_OPERATOR_ALPHA, "empty");
+        String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
 
         String onsl = s.getOperatorAlphaLong();
         String onss = s.getOperatorAlphaShort();
@@ -1331,7 +1225,7 @@
         boolean equalsOnsl = onsl != null && spn.equals(onsl);
         boolean equalsOnss = onss != null && spn.equals(onss);
 
-        String simNumeric = SystemProperties.get(PROPERTY_SIM_OPERATOR_NUMERIC, "");
+        String simNumeric = SystemProperties.get(PROPERTY_ICC_OPERATOR_NUMERIC, "");
         String  operatorNumeric = s.getOperatorNumeric();
 
         boolean equalsMcc = true;
@@ -1345,8 +1239,7 @@
     }
 
     private static
-    int twoDigitsAt(String s, int offset)
-    {
+    int twoDigitsAt(String s, int offset) {
         int a, b;
 
         a = Character.digit(s.charAt(offset), 10);
@@ -1631,7 +1524,7 @@
                     + (SystemClock.elapsedRealtime() - mSavedAtTime));
         }
     }
-    
+
     /**
      * Post a notification to NotificationManager for restricted state
      * 
@@ -1640,7 +1533,6 @@
     private void setNotification(int notifyType) {
 
         Log.d(LOG_TAG, "[DSAC DEB] " + "create notification " + notifyType);
-        
         Context context = phone.getContext();
 
         mNotification = new Notification();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
new file mode 100644
index 0000000..c163803
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.telephony.PhoneNumberUtils;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsAddress;
+
+public class GsmSmsAddress extends SmsAddress {
+
+    static final int OFFSET_ADDRESS_LENGTH = 0;
+
+    static final int OFFSET_TOA = 1;
+
+    static final int OFFSET_ADDRESS_VALUE = 2;
+
+    /**
+     * New GsmSmsAddress from TS 23.040 9.1.2.5 Address Field
+     *
+     * @param offset the offset of the Address-Length byte
+     * @param length the length in bytes rounded up, e.g. "2 +
+     *        (addressLength + 1) / 2"
+     */
+
+    public GsmSmsAddress(byte[] data, int offset, int length) {
+        origBytes = new byte[length];
+        System.arraycopy(data, offset, origBytes, 0, length);
+
+        // addressLength is the count of semi-octets, not bytes
+        int addressLength = origBytes[OFFSET_ADDRESS_LENGTH] & 0xff;
+
+        int toa = origBytes[OFFSET_TOA] & 0xff;
+        ton = 0x7 & (toa >> 4);
+
+        // TOA must have its high bit set
+        if ((toa & 0x80) != 0x80) {
+            throw new RuntimeException("Invalid TOA - high bit must be set");
+        }
+
+        if (isAlphanumeric()) {
+            // An alphanumeric address
+            int countSeptets = addressLength * 4 / 7;
+
+            address = GsmAlphabet.gsm7BitPackedToString(origBytes,
+                    OFFSET_ADDRESS_VALUE, countSeptets);
+        } else {
+            // TS 23.040 9.1.2.5 says
+            // that "the MS shall interpret reserved values as 'Unknown'
+            // but shall store them exactly as received"
+
+            byte lastByte = origBytes[length - 1];
+
+            if ((addressLength & 1) == 1) {
+                // Make sure the final unused BCD digit is 0xf
+                origBytes[length - 1] |= 0xf0;
+            }
+            address = PhoneNumberUtils.calledPartyBCDToString(origBytes,
+                    OFFSET_TOA, length - OFFSET_TOA);
+
+            // And restore origBytes
+            origBytes[length - 1] = lastByte;
+        }
+    }
+
+    public String getAddressString() {
+        return address;
+    }
+
+    /**
+     * Returns true if this is an alphanumeric address
+     */
+    public boolean isAlphanumeric() {
+        return ton == TON_ALPHANUMERIC;
+    }
+
+    public boolean isNetworkSpecific() {
+        return ton == TON_NETWORK;
+    }
+
+    /**
+     * Returns true of this is a valid CPHS voice message waiting indicator
+     * address
+     */
+    public boolean isCphsVoiceMessageIndicatorAddress() {
+        // CPHS-style MWI message
+        // See CPHS 4.7 B.4.2.1
+        //
+        // Basically:
+        //
+        // - Originating address should be 4 bytes long and alphanumeric
+        // - Decode will result with two chars:
+        // - Char 1
+        // 76543210
+        // ^ set/clear indicator (0 = clear)
+        // ^^^ type of indicator (000 = voice)
+        // ^^^^ must be equal to 0001
+        // - Char 2:
+        // 76543210
+        // ^ line number (0 = line 1)
+        // ^^^^^^^ set to 0
+        //
+        // Remember, since the alpha address is stored in 7-bit compact form,
+        // the "line number" is really the top bit of the first address value
+        // byte
+
+        return (origBytes[OFFSET_ADDRESS_LENGTH] & 0xff) == 4
+                && isAlphanumeric() && (origBytes[OFFSET_TOA] & 0x0f) == 0;
+    }
+
+    /**
+     * Returns true if this is a valid CPHS voice message waiting indicator
+     * address indicating a "set" of "indicator 1" of type "voice message
+     * waiting"
+     */
+    public boolean isCphsVoiceMessageSet() {
+        // 0x11 means "set" "voice message waiting" "indicator 1"
+        return isCphsVoiceMessageIndicatorAddress()
+                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x11;
+
+    }
+
+    /**
+     * Returns true if this is a valid CPHS voice message waiting indicator
+     * address indicating a "clear" of "indicator 1" of type "voice message
+     * waiting"
+     */
+    public boolean isCphsVoiceMessageClear() {
+        // 0x10 means "clear" "voice message waiting" "indicator 1"
+        return isCphsVoiceMessageIndicatorAddress()
+                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x10;
+
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
index c600530..d88d0b7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
@@ -16,11 +16,11 @@
 
 package com.android.internal.telephony.gsm;
 
-/** 
+/**
  * Used to indicate that the NetworkInfo object is parcelable to aidl.
  * This is a simple effort to make NetworkInfo parcelable rather than
  * trying to make the conventional containing object (AsyncResult),
- * implement parcelable.  This functionality is needed for the 
+ * implement parcelable.  This functionality is needed for the
  * NetworkQueryService to fix 1128695
  */
 parcelable NetworkInfo;
diff --git a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
index bebf9ba..04fd13e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
+++ b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
@@ -22,8 +22,7 @@
 /**
  * {@hide}
  */
-public class NetworkInfo implements Parcelable
-{
+public class NetworkInfo implements Parcelable {
     public enum State {
         UNKNOWN,
         AVAILABLE,
@@ -39,34 +38,29 @@
 
 
     public String
-    getOperatorAlphaLong()
-    {
+    getOperatorAlphaLong() {
         return operatorAlphaLong;
     }
 
     public String
-    getOperatorAlphaShort()
-    {
+    getOperatorAlphaShort() {
         return operatorAlphaShort;
     }
 
     public String
-    getOperatorNumeric()
-    {
+    getOperatorNumeric() {
         return operatorNumeric;
     }
 
     public State
-    getState()
-    {
+    getState() {
         return state;
     }
 
-    NetworkInfo(String operatorAlphaLong, 
-                String operatorAlphaShort, 
-                String operatorNumeric, 
-                State state)
-    {
+    NetworkInfo(String operatorAlphaLong,
+                String operatorAlphaShort,
+                String operatorNumeric,
+                State state) {
 
         this.operatorAlphaLong = operatorAlphaLong;
         this.operatorAlphaShort = operatorAlphaShort;
@@ -76,20 +70,18 @@
     }
 
 
-    NetworkInfo(String operatorAlphaLong, 
-                String operatorAlphaShort, 
-                String operatorNumeric, 
-                String stateString)
-    {
-        this (operatorAlphaLong, operatorAlphaShort, 
+    public NetworkInfo(String operatorAlphaLong,
+                String operatorAlphaShort,
+                String operatorNumeric,
+                String stateString) {
+        this (operatorAlphaLong, operatorAlphaShort,
                 operatorNumeric, rilStateToState(stateString));
     }
 
     /**
      * See state strings defined in ril.h RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
      */
-    private static State rilStateToState(String s)
-    {
+    private static State rilStateToState(String s) {
         if (s.equals("unknown")) {
             return State.UNKNOWN;
         } else if (s.equals("available")) {
@@ -105,29 +97,28 @@
     }
 
 
-    public String toString()
-    {
-        return "NetworkInfo " + operatorAlphaLong 
-                + "/" + operatorAlphaShort 
-                + "/" + operatorNumeric 
+    public String toString() {
+        return "NetworkInfo " + operatorAlphaLong
+                + "/" + operatorAlphaShort
+                + "/" + operatorNumeric
                 + "/" + state;
     }
-    
-    /** 
+
+    /**
      * Parcelable interface implemented below.
      * This is a simple effort to make NetworkInfo parcelable rather than
      * trying to make the conventional containing object (AsyncResult),
-     * implement parcelable.  This functionality is needed for the 
+     * implement parcelable.  This functionality is needed for the
      * NetworkQueryService to fix 1128695.
      */
-    
+
     public int describeContents() {
         return 0;
     }
 
-    /** 
+    /**
      * Implement the Parcelable interface.
-     * Method to serialize a NetworkInfo object. 
+     * Method to serialize a NetworkInfo object.
      */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(operatorAlphaLong);
@@ -136,9 +127,9 @@
         dest.writeSerializable(state);
     }
 
-    /** 
+    /**
      * Implement the Parcelable interface
-     * Method to deserialize a NetworkInfo object, or an array thereof. 
+     * Method to deserialize a NetworkInfo object, or an array thereof.
      */
     public static final Creator<NetworkInfo> CREATOR =
         new Creator<NetworkInfo>() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java b/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
index d5d481a..31cdacf 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
@@ -19,10 +19,9 @@
 /**
  * {@hide}
  */
-public class PDPContextState
-{
+public class PDPContextState {
     public int cid;
-    public boolean active;
+    public int active;
     public String type;
     public String apn;
     public String address;
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
index 66f8b72..88acb1b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
@@ -17,88 +17,26 @@
 package com.android.internal.telephony.gsm;
 
 import android.os.*;
-import android.database.Cursor;
-import android.provider.Telephony;
 import android.text.util.Regex;
 import android.util.EventLog;
 import android.util.Log;
 
-import java.util.ArrayList;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataLink;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyEventLog;
 
 /**
  * {@hide}
  */
-public class PdpConnection extends Handler {
+public class PdpConnection extends DataConnection {
 
     private static final String LOG_TAG = "GSM";
     private static final boolean DBG  = true;
     private static final boolean FAKE_FAIL = false;
 
-    public enum PdpState {
-        ACTIVE,     /* has active pdp context */
-        ACTIVATING, /* during connecting process */
-        INACTIVE;    /* has empty pdp context */
-
-        public String toString() {
-            switch (this) {
-                case ACTIVE: return "active";
-                case ACTIVATING: return "setting up";
-                default: return "inactive";
-            }
-        }
-
-        public boolean isActive() {
-            return this == ACTIVE;
-        }
-
-        public boolean isInactive() {
-            return this == INACTIVE;
-        }
-    }
-
-    public enum PdpFailCause {
-        NONE,
-        BAD_APN,
-        BAD_PAP_SECRET,
-        BARRED,
-        USER_AUTHENTICATION,
-        SERVICE_OPTION_NOT_SUPPORTED,
-        SERVICE_OPTION_NOT_SUBSCRIBED,
-        SIM_LOCKED,
-        RADIO_OFF,
-        NO_SIGNAL,
-        NO_DATA_PLAN,
-        RADIO_NOT_AVIALABLE,
-        SUSPENED_TEMPORARY,
-        RADIO_ERROR_RETRY,
-        UNKNOWN;
-
-        public boolean isPermanentFail() {
-            return (this == RADIO_OFF);
-        }
-
-        public String toString() {
-            switch (this) {
-                case NONE: return "no error";
-                case BAD_APN: return "bad apn";
-                case BAD_PAP_SECRET:return "bad pap secret";
-                case BARRED: return "barred";
-                case USER_AUTHENTICATION: return "error user autentication";
-                case SERVICE_OPTION_NOT_SUPPORTED: return "data not supported";
-                case SERVICE_OPTION_NOT_SUBSCRIBED: return "datt not subcribed";
-                case SIM_LOCKED: return "sim locked";
-                case RADIO_OFF: return "radio is off";
-                case NO_SIGNAL: return "no signal";
-                case NO_DATA_PLAN: return "no data plan";
-                case RADIO_NOT_AVIALABLE: return "radio not available";
-                case SUSPENED_TEMPORARY: return "suspend temporary";
-                case RADIO_ERROR_RETRY: return "transient radio error";
-                default: return "unknown data error";
-            }
-        }
-    }
-
     /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */
     private static final int PDP_FAIL_RIL_BARRED = 8;
     private static final int PDP_FAIL_RIL_BAD_APN = 27;
@@ -107,54 +45,20 @@
     private static final int PDP_FAIL_RIL_SERVICE_OPTION_NOT_SUBSCRIBED = 33;
     private static final int PDP_FAIL_RIL_ERROR_UNSPECIFIED = 0xffff;
 
-    //***** Event codes
-    private static final int EVENT_SETUP_PDP_DONE = 1;
-    private static final int EVENT_GET_LAST_FAIL_DONE = 2;
-    private static final int EVENT_LINK_STATE_CHANGED = 3;
-    private static final int EVENT_DEACTIVATE_DONE = 4;
-    private static final int EVENT_FORCE_RETRY = 5;
-
     //***** Instance Variables
-    private GSMPhone phone;
     private String pdp_name;
-    private PdpState state;
-    private Message onConnectCompleted;
-    private Message onDisconnect;
-    private int cid;
-    private long createTime;
-    private long lastFailTime;
-    private PdpFailCause lastFailCause;
     private ApnSetting apn;
-    private String interfaceName;
-    private String ipAddress;
-    private String gatewayAddress;
-    private String[] dnsServers;
-
-    private static final String NULL_IP = "0.0.0.0";
 
     // dataLink is only used to support pppd link
-    DataLink dataLink;
-    // receivedDisconnectReq is set when disconnect pdp link during activating
-    private boolean receivedDisconnectReq;
+    private DataLink dataLink;
 
     //***** Constructor
-    PdpConnection(GSMPhone phone)
-    {
-        this.phone = phone;
-        this.state = PdpState.INACTIVE;
-        onConnectCompleted = null;
-        onDisconnect = null;
-        this.cid = -1;
-        this.createTime = -1;
-        this.lastFailTime = -1;
-        this.lastFailCause = PdpFailCause.NONE;
-        this.apn = null;
+    PdpConnection(GSMPhone phone) {
+        super(phone);
         this.dataLink = null;
-        receivedDisconnectReq = false;
-        this.dnsServers = new String[2];
 
         if (SystemProperties.get("ro.radio.use-ppp","no").equals("yes")) {
-            dataLink = new PppLink(phone.mDataConnection);
+            dataLink = new PppLink((GsmDataConnectionTracker) phone.mDataConnection, phone);
             dataLink.setOnLinkChange(this, EVENT_LINK_STATE_CHANGED, null);
         }
     }
@@ -171,37 +75,37 @@
 
         setHttpProxy (apn.proxy, apn.port);
 
-        state = PdpState.ACTIVATING;
+        state = State.ACTIVATING;
         this.apn = apn;
         onConnectCompleted = onCompleted;
         createTime = -1;
         lastFailTime = -1;
-        lastFailCause = PdpFailCause.NONE;
+        lastFailCause = FailCause.NONE;
         receivedDisconnectReq = false;
 
         if (FAKE_FAIL) {
             // for debug before baseband implement error in setup PDP
             if (apn.apn.equalsIgnoreCase("badapn")){
-                notifyFail(PdpFailCause.BAD_APN, onConnectCompleted);
+                notifyFail(FailCause.BAD_APN, onConnectCompleted);
                 return;
             }
         }
 
-        phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,
-                obtainMessage(EVENT_SETUP_PDP_DONE));
+        phone.mCM.setupDataCall(Integer.toString(RILConstants.GSM_PHONE), null, apn.apn, apn.user,
+                apn.password, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
     }
 
-    void disconnect(Message msg) {
+    protected void disconnect(Message msg) {
         onDisconnect = msg;
-        if (state == PdpState.ACTIVE) {
+        if (state == State.ACTIVE) {
             if (dataLink != null) {
                 dataLink.disconnect();
             }
 
             if (phone.mCM.getRadioState().isOn()) {
-                phone.mCM.deactivateDefaultPDP(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
+                phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
             }
-        } else if (state == PdpState.ACTIVATING) {
+        } else if (state == State.ACTIVATING) {
             receivedDisconnectReq = true;
         } else {
             // state == INACTIVE.  Nothing to do, so notify immediately.
@@ -209,20 +113,9 @@
         }
     }
 
-    private void
-    setHttpProxy(String httpProxy, String httpPort)
-    {
-        if (httpProxy == null || httpProxy.length() == 0) {
-            phone.setSystemProperty("net.gprs.http-proxy", null);
-            return;
-        }
-
-        if (httpPort == null || httpPort.length() == 0) {
-            httpPort = "8080";     // Default to port 8080
-        }
-
-        phone.setSystemProperty("net.gprs.http-proxy",
-                "http://" + httpProxy + ":" + httpPort + "/");
+    public void clearSettings() {
+        super.clearSettings();
+        apn = null;
     }
 
     public String toString() {
@@ -231,61 +124,30 @@
                " lastFailCause=" + lastFailCause;
     }
 
-    public long getConnectionTime() {
-        return createTime;
-    }
 
-    public long getLastFailTime() {
-        return lastFailTime;
-    }
-
-    public PdpFailCause getLastFailCause() {
-        return lastFailCause;
-    }
-
-    public ApnSetting getApn() {
-        return apn;
-    }
-
-    String getInterface() {
-        return interfaceName;
-    }
-
-    String getIpAddress() {
-        return ipAddress;
-    }
-
-    String getGatewayAddress() {
-        return gatewayAddress;
-    }
-
-    String[] getDnsServers() {
-        return dnsServers;
-    }
-
-    public PdpState getState() {
-        return state;
-    }
-
-    private void notifyFail(PdpFailCause cause, Message onCompleted) {
+    protected void notifyFail(FailCause cause, Message onCompleted) {
         if (onCompleted == null) return;
 
-        state = PdpState.INACTIVE;
+        state = State.INACTIVE;
         lastFailCause = cause;
         lastFailTime = System.currentTimeMillis();
         onConnectCompleted = null;
 
-        if (DBG) log("Notify PDP fail at " + lastFailTime
-                + " due to " + lastFailCause);
+        if (DBG) {
+            log("Notify PDP fail at " + lastFailTime +
+                    " due to " + lastFailCause);
+        }
 
         AsyncResult.forMessage(onCompleted, cause, new Exception());
         onCompleted.sendToTarget();
     }
 
-    private void notifySuccess(Message onCompleted) {
-        if (onCompleted == null) return;
+    protected void notifySuccess(Message onCompleted) {
+        if (onCompleted == null) {
+            return;
+        }
 
-        state = PdpState.ACTIVE;
+        state = State.ACTIVE;
         createTime = System.currentTimeMillis();
         onConnectCompleted = null;
         onCompleted.arg1 = cid;
@@ -296,7 +158,7 @@
         onCompleted.sendToTarget();
     }
 
-    private void notifyDisconnect(Message msg) {
+    protected void notifyDisconnect(Message msg) {
         if (DBG) log("Notify PDP disconnect");
 
         if (msg != null) {
@@ -306,22 +168,7 @@
         clearSettings();
     }
 
-    void clearSettings() {
-        state = PdpState.INACTIVE;
-        receivedDisconnectReq = false;
-        createTime = -1;
-        lastFailTime = -1;
-        lastFailCause = PdpFailCause.NONE;
-        apn = null;
-        onConnectCompleted = null;
-        interfaceName = null;
-        ipAddress = null;
-        gatewayAddress = null;
-        dnsServers[0] = null;
-        dnsServers[1] = null;
-    }
-
-    private void onLinkStateChanged(DataLink.LinkState linkState) {
+    protected void onLinkStateChanged(DataLink.LinkState linkState) {
         switch (linkState) {
             case LINK_UP:
                 notifySuccess(onConnectCompleted);
@@ -335,151 +182,110 @@
         }
     }
 
-    private PdpFailCause getFailCauseFromRequest(int rilCause) {
-        PdpFailCause cause;
+    protected FailCause getFailCauseFromRequest(int rilCause) {
+        FailCause cause;
 
         switch (rilCause) {
             case PDP_FAIL_RIL_BARRED:
-                cause = PdpFailCause.BARRED;
+                cause = FailCause.BARRED;
                 break;
             case PDP_FAIL_RIL_BAD_APN:
-                cause = PdpFailCause.BAD_APN;
+                cause = FailCause.BAD_APN;
                 break;
             case PDP_FAIL_RIL_USER_AUTHENTICATION:
-                cause = PdpFailCause.USER_AUTHENTICATION;
+                cause = FailCause.USER_AUTHENTICATION;
                 break;
             case PDP_FAIL_RIL_SERVICE_OPTION_NOT_SUPPORTED:
-                cause = PdpFailCause.SERVICE_OPTION_NOT_SUPPORTED;
+                cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
                 break;
             case PDP_FAIL_RIL_SERVICE_OPTION_NOT_SUBSCRIBED:
-                cause = PdpFailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
+                cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
                 break;
             default:
-                cause = PdpFailCause.UNKNOWN;
+                cause = FailCause.UNKNOWN;
         }
         return cause;
     }
 
-
-    private void log(String s) {
+    protected void log(String s) {
         Log.d(LOG_TAG, "[PdpConnection] " + s);
     }
 
     @Override
-    public void handleMessage(Message msg) {
-        AsyncResult ar;
+    protected void onDeactivated(AsyncResult ar) {
+        notifyDisconnect((Message) ar.userObj);
+        if (DBG) log("PDP Connection Deactivated");
+    }
 
-        switch (msg.what) {
-            case EVENT_SETUP_PDP_DONE:
-                ar = (AsyncResult) msg.obj;
+    @Override
+    protected void onSetupConnectionCompleted(AsyncResult ar) {
+        if (ar.exception != null) {
+            Log.e(LOG_TAG, "PDP Context Init failed " + ar.exception);
 
-                if (ar.exception != null) {
-                    Log.e(LOG_TAG, "PDP Context Init failed " + ar.exception);
+            if (receivedDisconnectReq) {
+                // Don't bother reporting the error if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                notifyDisconnect(onDisconnect);
+            } else {
+                if ( ar.exception instanceof CommandException &&
+                        ((CommandException) (ar.exception)).getCommandError()
+                        == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                    notifyFail(FailCause.RADIO_NOT_AVAILABLE,
+                            onConnectCompleted);
+                } else {
+                    phone.mCM.getLastPdpFailCause(
+                            obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                }
+            }
+        } else {
+            if (receivedDisconnectReq) {
+                // Don't bother reporting success if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                disconnect(onDisconnect);
+            } else {
+                String[] response = ((String[]) ar.result);
+                cid = Integer.parseInt(response[0]);
 
-                    if (receivedDisconnectReq) {
-                        // Don't bother reporting the error if there's already a
-                        // pending disconnect request, since DataConnectionTracker
-                        // has already updated its state.
-                        notifyDisconnect(onDisconnect);
-                    } else {
-                        if ( ar.exception instanceof CommandException &&
-                                ((CommandException) (ar.exception)).getCommandError()
-                                == CommandException.Error.RADIO_NOT_AVAILABLE) {
-                            notifyFail(PdpFailCause.RADIO_NOT_AVIALABLE,
-                                    onConnectCompleted);
-                        } else {
-                            phone.mCM.getLastPdpFailCause(
-                                    obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                if (response.length > 2) {
+                    interfaceName = response[1];
+                    ipAddress = response[2];
+                    String prefix = "net." + interfaceName + ".";
+                    gatewayAddress = SystemProperties.get(prefix + "gw");
+                    dnsServers[0] = SystemProperties.get(prefix + "dns1");
+                    dnsServers[1] = SystemProperties.get(prefix + "dns2");
+                    if (DBG) {
+                        log("interface=" + interfaceName + " ipAddress=" + ipAddress
+                            + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0]
+                            + " DNS2=" + dnsServers[1]);
+                    }
+
+                    if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])
+                                        && !((GSMPhone) phone).isDnsCheckDisabled()) {
+                        // Work around a race condition where QMI does not fill in DNS:
+                        // Deactivate PDP and let DataConnectionTracker retry.
+                        // Do not apply the race condition workaround for MMS APN
+                        // if Proxy is an IP-address.
+                        // Otherwise, the default APN will not be restored anymore.
+                        if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
+                                || !isIpAddress(apn.mmsProxy)) {
+                            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
+                                    dnsServers[0]);
+                            phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_FORCE_RETRY));
+                            return;
                         }
                     }
-                } else {
-                    if (receivedDisconnectReq) {
-                        // Don't bother reporting success if there's already a
-                        // pending disconnect request, since DataConnectionTracker
-                        // has already updated its state.
-                        // Set ACTIVE so that disconnect does the right thing.
-                        state = PdpState.ACTIVE;
-                        disconnect(onDisconnect);
-                    } else {
-                        String[] response = ((String[]) ar.result);
-                        cid = Integer.parseInt(response[0]);
-
-                        if (response.length > 2) {
-                            interfaceName = response[1];
-                            ipAddress = response[2];
-                            String prefix = "net." + interfaceName + ".";
-                            gatewayAddress = SystemProperties.get(prefix + "gw");
-                            dnsServers[0] = SystemProperties.get(prefix + "dns1");
-                            dnsServers[1] = SystemProperties.get(prefix + "dns2");
-                            if (DBG) {
-                                log("interface=" + interfaceName + " ipAddress=" + ipAddress
-                                    + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0]
-                                    + " DNS2=" + dnsServers[1]);
-                            }
-
-                            if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])
-                                    && !phone.isDnsCheckDisabled()) {
-                                // Work around a race condition where QMI does not fill in DNS:
-                                // Deactivate PDP and let DataConnectionTracker retry.
-                                // Do not apply the race condition workaround for MMS APN
-                                // if Proxy is an IP-address.
-                                // Otherwise, the default APN will not be restored anymore.
-                                if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
-                                        || !isIpAddress(apn.mmsProxy)) {
-                                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
-                                            dnsServers[0]);
-                                    phone.mCM.deactivateDefaultPDP(cid,
-                                            obtainMessage(EVENT_FORCE_RETRY));
-                                    break;
-                                }
-                            }
-                        }
-
-                        if (dataLink != null) {
-                            dataLink.connect();
-                        } else {
-                            onLinkStateChanged(DataLink.LinkState.LINK_UP);
-                        }
-
-                        if (DBG) log("PDP setup on cid = " + cid);
-                    }
-                }
-                break;
-            case EVENT_FORCE_RETRY:
-                if (receivedDisconnectReq) {
-                    notifyDisconnect(onDisconnect);
-                } else {
-                    ar = (AsyncResult) msg.obj;
-                    notifyFail(PdpFailCause.RADIO_ERROR_RETRY, onConnectCompleted);
-                }
-                break;
-            case EVENT_GET_LAST_FAIL_DONE:
-                if (receivedDisconnectReq) {
-                    // Don't bother reporting the error if there's already a
-                    // pending disconnect request, since DataConnectionTracker
-                    // has already updated its state.
-                    notifyDisconnect(onDisconnect);
-                } else {
-                    ar = (AsyncResult) msg.obj;
-                    PdpFailCause cause = PdpFailCause.UNKNOWN;
-
-                    if (ar.exception == null) {
-                        int rilFailCause = ((int[]) (ar.result))[0];
-                        cause = getFailCauseFromRequest(rilFailCause);
-                    }
-                    notifyFail(cause, onConnectCompleted);
                 }
 
-                break;
-            case EVENT_LINK_STATE_CHANGED:
-                ar = (AsyncResult) msg.obj;
-                DataLink.LinkState ls  = (DataLink.LinkState) ar.result;
-                onLinkStateChanged(ls);
-                break;
-            case EVENT_DEACTIVATE_DONE:
-                ar = (AsyncResult) msg.obj;
-                notifyDisconnect((Message) ar.userObj);
-                break;
+                if (dataLink != null) {
+                    dataLink.connect();
+                } else {
+                    onLinkStateChanged(DataLink.LinkState.LINK_UP);
+                }
+
+                if (DBG) log("PDP setup on cid = " + cid);
+            }
         }
     }
 
@@ -488,4 +294,8 @@
 
         return Regex.IP_ADDRESS_PATTERN.matcher(apn.mmsProxy).matches();
     }
+
+    public ApnSetting getApn() {
+        return this.apn;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/PppLink.java b/telephony/java/com/android/internal/telephony/gsm/PppLink.java
index 43d4f1f..9627696 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PppLink.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PppLink.java
@@ -16,28 +16,31 @@
 
 package com.android.internal.telephony.gsm;
 
+import android.database.Cursor;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.os.SystemService;
+import android.util.Log;
+
+import com.android.internal.telephony.DataLink;
+import com.android.internal.telephony.DataConnectionTracker.State;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.util.ArrayUtils;
+
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 
-import android.database.Cursor;
-import android.os.Message;
-import android.os.SystemProperties;
-import android.os.SystemService;
-import com.android.internal.telephony.gsm.DataConnectionTracker.State;
-import com.android.internal.util.ArrayUtils;
-import android.util.Log;
-
 /**
  * Represents a PPP link.
- * 
+ *
  * Ideally this would be managed by the RIL implementation, but
  * we currently have implementations where this is not the case.
  *
  * {@hide}
  */
-final class PppLink extends DataLink implements DataLinkInterface {
+final class PppLink extends DataLink {
     private static final String LOG_TAG = "GSM";
 
     static final String PATH_PPP_OPERSTATE = "/sys/class/net/ppp0/operstate";
@@ -69,11 +72,14 @@
     };
     private final byte[] mCheckPPPBuffer = new byte[32];
 
+    private PhoneBase phone;
+
     int lastPppdExitCode = EXIT_OK;
 
 
-    PppLink(DataConnectionTracker dc) {
+    PppLink(GsmDataConnectionTracker dc, GSMPhone p) {
         super(dc);
+        this.phone = p;
     }
 
     public void connect() {
@@ -131,7 +137,7 @@
                 checkPPP();
 
                 // keep polling in case interface goes down
-                if (dataConnection.state != State.IDLE) {                    
+                if (dataConnection.getState() != State.IDLE) {
                     Message poll = obtainMessage();
                     poll.what = EVENT_POLL_DATA_CONNECTION;
                     sendMessageDelayed(poll, POLL_SYSFS_MILLIS);
@@ -141,7 +147,7 @@
     }
 
     private void checkPPP() {
-        boolean connecting = (dataConnection.state == State.CONNECTING);
+        boolean connecting = (dataConnection.getState() == State.CONNECTING);
 
         try {
             RandomAccessFile file = new RandomAccessFile(PATH_PPP_OPERSTATE, "r");
@@ -152,10 +158,10 @@
             // "unknown" where one might otherwise expect "up"
             if (ArrayUtils.equals(mCheckPPPBuffer, UP_ASCII_STRING, UP_ASCII_STRING.length)
                     || ArrayUtils.equals(mCheckPPPBuffer, UNKNOWN_ASCII_STRING,
-                            UNKNOWN_ASCII_STRING.length) 
-                            && dataConnection.state == State.CONNECTING) {
+                    UNKNOWN_ASCII_STRING.length)
+                    && dataConnection.getState() == State.CONNECTING) {
 
-                Log.i(LOG_TAG, 
+                Log.i(LOG_TAG,
                 "found ppp interface. Notifying GPRS connected");
 
                 if (mLinkChangeRegistrant != null) {
@@ -163,23 +169,23 @@
                 }
 
                 connecting = false;
-            } else if (dataConnection.state == State.CONNECTED 
+            } else if (dataConnection.getState() == State.CONNECTED
                     && ArrayUtils.equals(mCheckPPPBuffer, DOWN_ASCII_STRING,
-                            DOWN_ASCII_STRING.length)) {
+                    DOWN_ASCII_STRING.length)) {
 
-                Log.i(LOG_TAG, 
+                Log.i(LOG_TAG,
                 "ppp interface went down. Reconnecting...");
 
                 if (mLinkChangeRegistrant != null) {
                     mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN);
                 }
-            }                                    
+            }
         } catch (IOException ex) {
             if (! (ex instanceof FileNotFoundException)) {
                 Log.i(LOG_TAG, "Poll ppp0 ex " + ex.toString());
             }
 
-            if (dataConnection.state == State.CONNECTED &&
+            if (dataConnection.getState() == State.CONNECTED &&
                     mLinkChangeRegistrant != null) {
                 mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN);
             }
@@ -206,4 +212,8 @@
         }
 
     }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[PppLink] " + s);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/RILConstants.java b/telephony/java/com/android/internal/telephony/gsm/RILConstants.java
deleted file mode 100644
index 4463b20..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/RILConstants.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-
-/**
- * {@hide}
- */
-interface RILConstants
-{
-    // From the top of ril.cpp
-    int RIL_ERRNO_INVALID_RESPONSE = -1;
-
-    // from RIL_Errno
-    int SUCCESS = 0;
-    int RADIO_NOT_AVAILABLE = 1;     /* If radio did not start or is resetting */
-    int GENERIC_FAILURE = 2;
-    int PASSWORD_INCORRECT = 3;      /* for PIN/PIN2 methods only! */
-    int SIM_PIN2 = 4;                /* Operation requires SIM PIN2 to be entered */
-    int SIM_PUK2 = 5;                /* Operation requires SIM PIN2 to be entered */
-    int REQUEST_NOT_SUPPORTED = 6;
-    int REQUEST_CANCELLED = 7;
-    int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice call in class C */
-    int OP_NOT_ALLOWED_BEFORE_REG_NW = 9;     /* request is not allowed before device registers to network */
-    int SMS_SEND_FAIL_RETRY = 10;         /* send sms fail and need retry */
-/*
-cat include/telephony/ril.h | \
-   egrep '^#define' | \
-   sed -re 's/^#define +([^ ]+)* +([^ ]+)/    int \1 = \2;/' \
-   >>java/android/com.android.internal.telephony/gsm/RILConstants.java
-*/
-
-
-    int RIL_SIM_ABSENT = 0;
-    int RIL_SIM_NOT_READY = 1;
-    int RIL_SIM_READY = 2;
-    int RIL_SIM_PIN = 3;
-    int RIL_SIM_PUK = 4;
-    int RIL_SIM_NETWORK_PERSONALIZATION = 5;
-    
-    /** 
-     * No restriction at all including voice/SMS/USSD/SS/AV64 
-     * and packet data.
-     */   
-    int RIL_RESTRICTED_STATE_NONE = 0x00;    
-    /** 
-     * Block emergency call due to restriction. 
-     * But allow all normal voice/SMS/USSD/SS/AV64. 
-     */
-    int RIL_RESTRICTED_STATE_CS_EMERGENCY = 0x01;
-    /** 
-     * Block all normal voice/SMS/USSD/SS/AV64 due to restriction. 
-     * Only Emergency call allowed. 
-     */
-    int RIL_RESTRICTED_STATE_CS_NORMAL = 0x02;
-    /** 
-     * Block all voice/SMS/USSD/SS/AV64 
-     * including emergency call due to restriction.
-     */
-    int RIL_RESTRICTED_STATE_CS_ALL = 0x04;
-    /** 
-     * Block packet data access due to restriction. 
-     */  
-    int RIL_RESTRICTED_STATE_PS_ALL = 0x10;
-    
-    int RIL_REQUEST_GET_SIM_STATUS = 1;
-    int RIL_REQUEST_ENTER_SIM_PIN = 2;
-    int RIL_REQUEST_ENTER_SIM_PUK = 3;
-    int RIL_REQUEST_ENTER_SIM_PIN2 = 4;
-    int RIL_REQUEST_ENTER_SIM_PUK2 = 5;
-    int RIL_REQUEST_CHANGE_SIM_PIN = 6;
-    int RIL_REQUEST_CHANGE_SIM_PIN2 = 7;
-    int RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION = 8;
-    int RIL_REQUEST_GET_CURRENT_CALLS = 9;
-    int RIL_REQUEST_DIAL = 10;
-    int RIL_REQUEST_GET_IMSI = 11;
-    int RIL_REQUEST_HANGUP = 12;
-    int RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND = 13;
-    int RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND = 14;
-    int RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE = 15;
-    int RIL_REQUEST_CONFERENCE = 16;
-    int RIL_REQUEST_UDUB = 17;
-    int RIL_REQUEST_LAST_CALL_FAIL_CAUSE = 18;
-    int RIL_REQUEST_SIGNAL_STRENGTH = 19;
-    int RIL_REQUEST_REGISTRATION_STATE = 20;
-    int RIL_REQUEST_GPRS_REGISTRATION_STATE = 21;
-    int RIL_REQUEST_OPERATOR = 22;
-    int RIL_REQUEST_RADIO_POWER = 23;
-    int RIL_REQUEST_DTMF = 24;
-    int RIL_REQUEST_SEND_SMS = 25;
-    int RIL_REQUEST_SEND_SMS_EXPECT_MORE = 26;
-    int RIL_REQUEST_SETUP_DEFAULT_PDP = 27;
-    int RIL_REQUEST_SIM_IO = 28;
-    int RIL_REQUEST_SEND_USSD = 29;
-    int RIL_REQUEST_CANCEL_USSD = 30;
-    int RIL_REQUEST_GET_CLIR = 31;
-    int RIL_REQUEST_SET_CLIR = 32;
-    int RIL_REQUEST_QUERY_CALL_FORWARD_STATUS = 33;
-    int RIL_REQUEST_SET_CALL_FORWARD = 34;
-    int RIL_REQUEST_QUERY_CALL_WAITING = 35;
-    int RIL_REQUEST_SET_CALL_WAITING = 36;
-    int RIL_REQUEST_SMS_ACKNOWLEDGE = 37;
-    int RIL_REQUEST_GET_IMEI = 38;
-    int RIL_REQUEST_GET_IMEISV = 39;
-    int RIL_REQUEST_ANSWER = 40;
-    int RIL_REQUEST_DEACTIVATE_DEFAULT_PDP = 41;
-    int RIL_REQUEST_QUERY_FACILITY_LOCK = 42;
-    int RIL_REQUEST_SET_FACILITY_LOCK = 43;
-    int RIL_REQUEST_CHANGE_BARRING_PASSWORD = 44;
-    int RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE = 45;
-    int RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC = 46;
-    int RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL = 47;
-    int RIL_REQUEST_QUERY_AVAILABLE_NETWORKS = 48;
-    int RIL_REQUEST_DTMF_START = 49;
-    int RIL_REQUEST_DTMF_STOP = 50;
-    int RIL_REQUEST_BASEBAND_VERSION = 51;
-    int RIL_REQUEST_SEPARATE_CONNECTION = 52;
-    int RIL_REQUEST_SET_MUTE = 53;
-    int RIL_REQUEST_GET_MUTE = 54;
-    int RIL_REQUEST_QUERY_CLIP = 55;
-    int RIL_REQUEST_LAST_PDP_FAIL_CAUSE = 56;
-    int RIL_REQUEST_PDP_CONTEXT_LIST = 57;
-    int RIL_REQUEST_RESET_RADIO = 58;
-    int RIL_REQUEST_OEM_HOOK_RAW = 59;
-    int RIL_REQUEST_OEM_HOOK_STRINGS = 60;
-    int RIL_REQUEST_SCREEN_STATE = 61;
-    int RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION = 62;
-    int RIL_REQUEST_WRITE_SMS_TO_SIM = 63;
-    int RIL_REQUEST_DELETE_SMS_ON_SIM = 64;
-    int RIL_REQUEST_SET_BAND_MODE = 65;
-    int RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE = 66;
-    int RIL_REQUEST_STK_GET_PROFILE = 67;
-    int RIL_REQUEST_STK_SET_PROFILE = 68;
-    int RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND = 69;
-    int RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE = 70;
-    int RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM = 71;
-    int RIL_REQUEST_EXPLICIT_CALL_TRANSFER = 72;
-    int RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE = 73;
-    int RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE = 74;
-    int RIL_REQUEST_GET_NEIGHBORING_CELL_IDS = 75;
-    int RIL_REQUEST_SET_LOCATION_UPDATES = 76;
-    int RIL_UNSOL_RESPONSE_BASE = 1000;
-    int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
-    int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
-    int RIL_UNSOL_RESPONSE_NETWORK_STATE_CHANGED = 1002;
-    int RIL_UNSOL_RESPONSE_NEW_SMS = 1003;
-    int RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT = 1004;
-    int RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM = 1005;
-    int RIL_UNSOL_ON_USSD = 1006;
-    int RIL_UNSOL_ON_USSD_REQUEST = 1007;
-    int RIL_UNSOL_NITZ_TIME_RECEIVED = 1008;
-    int RIL_UNSOL_SIGNAL_STRENGTH = 1009;
-    int RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED = 1010;
-    int RIL_UNSOL_SUPP_SVC_NOTIFICATION = 1011;
-    int RIL_UNSOL_STK_SESSION_END = 1012;
-    int RIL_UNSOL_STK_PROACTIVE_COMMAND = 1013;
-    int RIL_UNSOL_STK_EVENT_NOTIFY = 1014;
-    int RIL_UNSOL_STK_CALL_SETUP = 1015;
-    int RIL_UNSOL_SIM_SMS_STORAGE_FULL = 1016;
-    int RIL_UNSOL_SIM_REFRESH = 1017;
-    int RIL_UNSOL_CALL_RING = 1018;
-    int RIL_UNSOL_RESTRICTED_STATE_CHANGED = 1023;
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
index 81fc657..a08cdde 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
@@ -16,506 +16,78 @@
 
 package com.android.internal.telephony.gsm;
 
-import com.android.internal.telephony.*;
-import com.android.internal.telephony.gsm.stk.ImageDescriptor;
-import android.os.*;
-import android.os.AsyncResult;
-import android.os.RegistrantList;
-import android.os.Registrant;
+import android.os.Message;
 import android.util.Log;
-import java.util.ArrayList;
+
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccFileHandler;
 
 /**
  * {@hide}
  */
-public final class SIMFileHandler extends Handler
-{
+public final class SIMFileHandler extends IccFileHandler implements IccConstants {
     static final String LOG_TAG = "GSM";
 
-    //from TS 11.11 9.1 or elsewhere
-    static private final int COMMAND_READ_BINARY = 0xb0;
-    static private final int COMMAND_UPDATE_BINARY = 0xd6;
-    static private final int COMMAND_READ_RECORD = 0xb2;
-    static private final int COMMAND_UPDATE_RECORD = 0xdc;
-    static private final int COMMAND_SEEK = 0xa2;
-    static private final int COMMAND_GET_RESPONSE = 0xc0;
-
-    // from TS 11.11 9.2.5
-    static private final int READ_RECORD_MODE_ABSOLUTE = 4;
-
-    //***** types of files  TS 11.11 9.3
-    static private final int EF_TYPE_TRANSPARENT = 0;
-    static private final int EF_TYPE_LINEAR_FIXED = 1;
-    static private final int EF_TYPE_CYCLIC = 3;
-
-    //***** types of files  TS 11.11 9.3
-    static private final int TYPE_RFU = 0;
-    static private final int TYPE_MF  = 1;
-    static private final int TYPE_DF  = 2;
-    static private final int TYPE_EF  = 4;
-    
-    // size of GET_RESPONSE for EF
-    static private final int GET_RESPONSE_EF_SIZE_BYTES = 15;
-
-    // Byte order received in response to COMMAND_GET_RESPONSE
-    // Refer TS 51.011 Section 9.2.1
-    static private final int RESPONSE_DATA_RFU_1 = 0;
-    static private final int RESPONSE_DATA_RFU_2 = 1;
-
-    static private final int RESPONSE_DATA_FILE_SIZE_1 = 2;
-    static private final int RESPONSE_DATA_FILE_SIZE_2 = 3;
-
-    static private final int RESPONSE_DATA_FILE_ID_1 = 4;
-    static private final int RESPONSE_DATA_FILE_ID_2 = 5;
-    static private final int RESPONSE_DATA_FILE_TYPE = 6;
-    static private final int RESPONSE_DATA_RFU_3 = 7;
-    static private final int RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
-    static private final int RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
-    static private final int RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
-    static private final int RESPONSE_DATA_FILE_STATUS = 11;
-    static private final int RESPONSE_DATA_LENGTH = 12;
-    static private final int RESPONSE_DATA_STRUCTURE = 13;
-    static private final int RESPONSE_DATA_RECORD_LENGTH = 14;
-
 
     //***** Instance Variables
-    GSMPhone phone;
-
-    //***** Events
-
-    /** Finished retrieving size of transparent EF; start loading. */
-    static private final int EVENT_GET_BINARY_SIZE_DONE = 4;
-    /** Finished loading contents of transparent EF; post result. */
-    static private final int EVENT_READ_BINARY_DONE = 5;
-    /** Finished retrieving size of records for linear-fixed EF; now load. */
-    static private final int EVENT_GET_RECORD_SIZE_DONE = 6;
-    /** Finished loading single record from a linear-fixed EF; post result. */
-    static private final int EVENT_READ_RECORD_DONE = 7;
-    /** Finished retrieving record size; post result. */
-    static private final int EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE = 8;
-    /** Finished retrieving image instance record; post result. */
-    static private final int EVENT_READ_IMG_DONE = 9;
-    /** Finished retrieving icon data; post result. */
-    static private final int EVENT_READ_ICON_DONE = 10;
-
-    //***** Inner Classes
-
-    static class LoadLinearFixedContext
-    {
-        
-        int efid;
-        int recordNum, recordSize, countRecords;
-        boolean loadAll;
-
-        Message onLoaded;
-
-        ArrayList<byte[]> results;
-
-        LoadLinearFixedContext(int efid, int recordNum, Message onLoaded)
-        {
-            this.efid = efid;
-            this.recordNum = recordNum;
-            this.onLoaded = onLoaded;
-            this.loadAll = false;
-        }
-
-        LoadLinearFixedContext(int efid, Message onLoaded)
-        {
-            this.efid = efid;
-            this.recordNum = 1;
-            this.loadAll = true;
-            this.onLoaded = onLoaded;
-        }
- 
-    }
-
 
     //***** Constructor
 
-    SIMFileHandler(GSMPhone phone)
-    {
-        this.phone = phone;
+    SIMFileHandler(GSMPhone phone) {
+        super(phone);
     }
 
-    //***** Public Methods
-
-    /**
-     * Load a record from a SIM Linear Fixed EF
-     *
-     * @param fileid EF id
-     * @param recordNum 1-based (not 0-based) record number
-     * @param onLoaded
-     *
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]     
-     *  
-     */
-    void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded)
-    {
-        Message response 
-            = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
-                        new LoadLinearFixedContext(fileid, recordNum, onLoaded));
-
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    public void dispose() {
+        super.dispose();
     }
 
-    /**
-     * Load a image instance record from a SIM Linear Fixed EF-IMG
-     * 
-     * @param recordNum 1-based (not 0-based) record number
-     * @param onLoaded
-     * 
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
-     * 
-     */
-    public void loadEFImgLinearFixed(int recordNum, Message onLoaded) {
-        Message response = obtainMessage(EVENT_READ_IMG_DONE,
-                new LoadLinearFixedContext(SimConstants.EF_IMG, recordNum,
-                        onLoaded));
-
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, SimConstants.EF_IMG, "img",
-                recordNum, READ_RECORD_MODE_ABSOLUTE,
-                ImageDescriptor.ID_LENGTH, null, null, response);
+    protected void finalize() {
+        Log.d(LOG_TAG, "SIMFileHandler finalized");
     }
 
-    /**
-     * get record size for a linear fixed EF
-     * 
-     * @param fileid EF id
-     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]
-     *        int[0] is the record length int[1] is the total length of the EF
-     *        file int[3] is the number of records in the EF file So int[0] *
-     *        int[3] = int[1]
-     */
-    void getEFLinearRecordSize(int fileid, Message onLoaded)
-    {
-        Message response
-                = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE,
-                        new LoadLinearFixedContext(fileid, onLoaded));
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                    0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    //***** Overridden from IccFileHandler
+
+    @Override
+    public void handleMessage(Message msg) {
+        super.handleMessage(msg);
     }
 
-    /**
-     * Load all records from a SIM Linear Fixed EF
-     *
-     * @param fileid EF id
-     * @param onLoaded
-     *
-     * ((AsyncResult)(onLoaded.obj)).result is an ArrayList<byte[]>
-     *  
-     */
-    void loadEFLinearFixedAll(int fileid, Message onLoaded)
-    {
-        Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
-                        new LoadLinearFixedContext(fileid,onLoaded));
+    protected String getEFPath(int efid) {
+        // TODO(): Make changes when USIM is supported
+        // TODO(): DF_GSM can be 7F20 or 7F21 to handle backward compatibility.
+        // Implement this after discussion with OEMs.
+        switch(efid) {
+        case EF_SMS:
+            return MF_SIM + DF_TELECOM;
 
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
-    }
+        case EF_EXT6:
+        case EF_MWIS:
+        case EF_MBI:
+        case EF_SPN:
+        case EF_AD:
+        case EF_MBDN:
+        case EF_PNN:
+        case EF_SPDI:
+        case EF_SST:
+        case EF_CFIS:
+            return MF_SIM + DF_GSM;
 
-    /**
-     * Load a SIM Transparent EF
-     *
-     * @param fileid EF id
-     * @param onLoaded
-     *
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]     
-     *  
-     */
-
-    void loadEFTransparent(int fileid, Message onLoaded)
-    {
-        Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
-                        fileid, 0, onLoaded);
-
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
-    }
-
-    /**
-     * Load a SIM Transparent EF-IMG. Used right after loadEFImgLinearFixed to
-     * retrive STK's icon data.
-     * 
-     * @param fileid EF id
-     * @param onLoaded
-     * 
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
-     * 
-     */
-    public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset,
-            int length, Message onLoaded) {
-        Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
-                onLoaded);
-
-        phone.mCM.simIO(COMMAND_READ_BINARY, fileid, "img", highOffset, lowOffset,
-                length, null, null, response);
-    }
-
-    /**
-     * Update a record in a linear fixed EF
-     * @param fileid EF id
-     * @param recordNum 1-based (not 0-based) record number
-     * @param data must be exactly as long as the record in the EF
-     * @param pin2 for CHV2 operations, otherwist must be null
-     * @param onComplete onComplete.obj will be an AsyncResult
-     *                   onComplete.obj.userObj will be a SimIoResult on success
-     */
-    void updateEFLinearFixed(int fileid, int recordNum, byte[] data,
-            String pin2, Message onComplete)
-    {
-        phone.mCM.simIO(COMMAND_UPDATE_RECORD, fileid, null,
-                        recordNum, READ_RECORD_MODE_ABSOLUTE, data.length,
-                        SimUtils.bytesToHexString(data), pin2, onComplete);
-    }
-
-    /**
-     * Update a transparent EF
-     * @param fileid EF id
-     * @param data must be exactly as long as the EF
-     */
-    void updateEFTransparent(int fileid, byte[] data, Message onComplete)
-    {
-        phone.mCM.simIO(COMMAND_UPDATE_BINARY, fileid, null,
-                        0, 0, data.length,
-                        SimUtils.bytesToHexString(data), null, onComplete);
-    }
-
-    //***** Overridden from Handler
-
-    public void handleMessage(Message msg)
-    {
-        AsyncResult ar;
-        SimIoResult result;
-        Message response = null;
-        String str;
-        LoadLinearFixedContext lc;
-
-        SimException simException;
-        byte data[];
-        int size;
-        int fileid;
-        int recordNum;
-        int recordSize[];
-
-        try {
-            switch (msg.what) {
-            case EVENT_READ_IMG_DONE:
-                ar = (AsyncResult) msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                simException = result.getException();
-                if (simException != null) {
-                    sendResult(response, result.payload, ar.exception);
-                }
-                break;
-            case EVENT_READ_ICON_DONE:
-                ar = (AsyncResult) msg.obj;
-                response = (Message) ar.userObj;
-                result = (SimIoResult) ar.result;
-
-                simException = result.getException();
-                if (simException != null) {
-                    sendResult(response, result.payload, ar.exception);
-                }
-                break;
-            case EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE:
-                ar = (AsyncResult)msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                data = result.payload;
-
-                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE] ||
-                    EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                recordSize = new int[3];
-                recordSize[0] = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
-                recordSize[1] = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
-                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
-                recordSize[2] = recordSize[1] / recordSize[0];
-
-                sendResult(response, recordSize, null);
-                break;
-             case EVENT_GET_RECORD_SIZE_DONE:
-                ar = (AsyncResult)msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                data = result.payload;
-                fileid = lc.efid;
-                recordNum = lc.recordNum;
-
-                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                lc.recordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
-
-                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
-                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
-
-                lc.countRecords = size / lc.recordSize;
-
-                 if (lc.loadAll) {
-                     lc.results = new ArrayList<byte[]>(lc.countRecords);
-                 }
-
-                 phone.mCM.simIO(COMMAND_READ_RECORD, lc.efid, null,
-                         lc.recordNum,
-                         READ_RECORD_MODE_ABSOLUTE,
-                         lc.recordSize, null, null,
-                         obtainMessage(EVENT_READ_RECORD_DONE, lc));
-                 break;
-            case EVENT_GET_BINARY_SIZE_DONE:
-                ar = (AsyncResult)msg.obj;
-                response = (Message) ar.userObj;
-                result = (SimIoResult) ar.result;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                data = result.payload;
-
-                fileid = msg.arg1;
-
-                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
-                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
-
-                phone.mCM.simIO(COMMAND_READ_BINARY, fileid, null,
-                                0, 0, size, null, null, 
-                                obtainMessage(EVENT_READ_BINARY_DONE,
-                                              fileid, 0, response));
-            break;
-
-            case EVENT_READ_RECORD_DONE:
-
-                ar = (AsyncResult)msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                if (!lc.loadAll) {
-                    sendResult(response, result.payload, null);
-                } else {
-                    lc.results.add(result.payload);
-
-                    lc.recordNum++;
-
-                    if (lc.recordNum > lc.countRecords) {
-                        sendResult(response, lc.results, null);
-                    } else {                   
-                        phone.mCM.simIO(COMMAND_READ_RECORD, lc.efid, null,
-                                    lc.recordNum,
-                                    READ_RECORD_MODE_ABSOLUTE,
-                                    lc.recordSize, null, null,
-                                    obtainMessage(EVENT_READ_RECORD_DONE, lc));
-                    }
-                }                
-
-            break;
-            
-            case EVENT_READ_BINARY_DONE:
-                ar = (AsyncResult)msg.obj;
-                response = (Message) ar.userObj;
-                result = (SimIoResult) ar.result;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                sendResult(response, result.payload, null);
-            break;
-
-        }} catch (Exception exc) {
-            if (response != null) {
-                sendResult(response, null, exc);
-            } else {
-                Log.e(LOG_TAG, "uncaught exception", exc);
-            }            
+        case EF_MAILBOX_CPHS:
+        case EF_VOICE_MAIL_INDICATOR_CPHS:
+        case EF_CFF_CPHS:
+        case EF_SPN_CPHS:
+        case EF_SPN_SHORT_CPHS:
+        case EF_INFO_CPHS:
+            return MF_SIM + DF_GSM;
         }
+        return getCommonIccEFPath(efid);
     }
 
-    //***** Private Methods
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[SIMFileHandler] " + msg);
+    }
 
-    private void sendResult(Message response, Object result, Throwable ex)
-    {
-        if (response == null) {
-            return;
-        }
-
-        AsyncResult.forMessage(response, result, ex);
-
-        response.sendToTarget();
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[SIMFileHandler] " + msg);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 4467536..f9015d9 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -16,26 +16,45 @@
 
 package com.android.internal.telephony.gsm;
 
+import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
+import android.app.IActivityManager;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.os.AsyncResult;
-import android.os.RegistrantList;
-import android.os.Registrant;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemProperties;
-import android.telephony.gsm.SmsMessage;
+import android.os.Registrant;
 import android.util.Log;
 import java.util.ArrayList;
 
+
 import static com.android.internal.telephony.TelephonyProperties.*;
-import com.android.internal.telephony.SimCard;
+
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.AdnRecordLoader;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.gsm.SimCard;
+import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.IccVmFixedException;
+import com.android.internal.telephony.IccVmNotSupportedException;
+import com.android.internal.telephony.PhoneProxy;
+
+
+
+
+
+
 
 /**
  * {@hide}
  */
-public final class SIMRecords extends Handler implements SimConstants
-{
+public final class SIMRecords extends IccRecords {
     static final String LOG_TAG = "GSM";
 
     private static final boolean CRASH_RIL = false;
@@ -44,37 +63,19 @@
 
     //***** Instance Variables
 
-    GSMPhone phone;
-    RegistrantList recordsLoadedRegistrants = new RegistrantList();
-
-    int recordsToLoad;  // number of pending load requests
-
-    AdnRecordCache adnCache;
-
     VoiceMailConstants mVmConfig;
+
+
     SpnOverride mSpnOverride;
     
     //***** Cached SIM State; cleared on channel close
 
-    boolean recordsRequested = false; // true if we've made requests for the sim records
-
     String imsi;
-    String iccid;
-    String msisdn = null;  // My mobile number
-    String msisdnTag = null;
-    String voiceMailNum = null;
-    String voiceMailTag = null;
-    String newVoiceMailNum = null;
-    String newVoiceMailTag = null;
-    boolean isVoiceMailFixed = false;
-    int countVoiceMessages = 0;
     boolean callForwardingEnabled;
-    int mncLength = 0;   // 0 is used to indicate that the value
-                         // is not initialized
-    int mailboxIndex = 0; // 0 is no mailbox dailing number associated
+
 
     /**
-     * Sates only used by getSpnFsm FSM
+     * States only used by getSpnFsm FSM
      */
     private Get_Spn_Fsm_State spnState;
 
@@ -157,9 +158,8 @@
 
     //***** Constructor
 
-    SIMRecords(GSMPhone phone)
-    {
-        this.phone = phone;
+    SIMRecords(GSMPhone p) {
+        super(p);
 
         adnCache = new AdnRecordCache(phone);
 
@@ -172,30 +172,35 @@
         recordsToLoad = 0;
 
 
-        phone.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
-        phone.mCM.registerForOffOrNotAvailable(
+        p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+        p.mCM.registerForOffOrNotAvailable(
                         this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
-        phone.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
-        phone.mCM.setOnSimRefresh(this, EVENT_SIM_REFRESH, null);
+        p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
+        p.mCM.setOnIccRefresh(this, EVENT_SIM_REFRESH, null);
 
         // Start off by setting empty state
-        onRadioOffOrNotAvailable();        
+        onRadioOffOrNotAvailable();
 
     }
 
-    AdnRecordCache getAdnCache() {
-        return adnCache;
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForSIMReady(this);
+        phone.mCM.unregisterForOffOrNotAvailable( this);
+        phone.mCM.unSetOnIccRefresh(this);
     }
 
-    private void onRadioOffOrNotAvailable()
-    {
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SIMRecords finalized");
+    }
+
+    protected void onRadioOffOrNotAvailable() {
         imsi = null;
         msisdn = null;
         voiceMailNum = null;
         countVoiceMessages = 0;
         mncLength = 0;
         iccid = null;
-        spn = null;
         // -1 means no EF_SPN found; treat accordingly.
         spnDisplayCondition = -1;
         efMWIS = null;
@@ -205,9 +210,9 @@
 
         adnCache.reset();
 
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_NUMERIC, null);
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, null);
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ISO_COUNTRY, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null);
 
         // recordsRequested is set to false indicating that the SIM
         // read requests made so far are not valid. This is set to
@@ -217,24 +222,13 @@
 
 
     //***** Public Methods
-    public void registerForRecordsLoaded(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant(h, what, obj);
-        recordsLoadedRegistrants.add(r);
-
-        if (recordsToLoad == 0 && recordsRequested == true) {
-            r.notifyRegistrant(new AsyncResult(null, null, null));
-        }
-    }
 
     /** Returns null if SIM is not yet ready */
-    public String getIMSI()
-    {
+    public String getIMSI() {
         return imsi;
     }
 
-    public String getMsisdnNumber()
-    {
+    public String getMsisdnNumber() {
         return msisdn;
     }
 
@@ -272,28 +266,18 @@
         return msisdnTag;
     }
 
-    public String getVoiceMailNumber()
-    {
+    public String getVoiceMailNumber() {
         return voiceMailNum;
     }
 
     /**
-     * Return Service Provider Name stored in SIM
-     * @return null if SIM is not yet ready
-     */
-    String getServiceProviderName()
-    {
-        return spn;
-    }
-
-    /**
      * Set voice mail number to SIM record
      *
      * The voice mail number can be stored either in EF_MBDN (TS 51.011) or
      * EF_MAILBOX_CPHS (CPHS 4.2)
      *
      * If EF_MBDN is available, store the voice mail number to EF_MBDN
-     * 
+     *
      * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS
      *
      * So the voice mail number will be stored in both EFs if both are available
@@ -314,7 +298,7 @@
             Message onComplete) {
         if (isVoiceMailFixed) {
             AsyncResult.forMessage((onComplete)).exception =
-                    new SimVmFixedException("Voicemail number is fixed by operator");
+                    new IccVmFixedException("Voicemail number is fixed by operator");
             onComplete.sendToTarget();
             return;
         }
@@ -336,9 +320,9 @@
                     EF_EXT1, 1, null,
                     obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, onComplete));
 
-        }else {
+        } else {
             AsyncResult.forMessage((onComplete)).exception =
-                    new SimVmNotSupportedException("Update SIM voice mailbox error");
+                    new IccVmNotSupportedException("Update SIM voice mailbox error");
             onComplete.sendToTarget();
         }
     }
@@ -352,12 +336,11 @@
      * Sets the SIM voice message waiting indicator records
      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
      * @param countWaiting The number of messages waiting, if known. Use
-     *                     -1 to indicate that an unknown number of 
+     *                     -1 to indicate that an unknown number of
      *                      messages are waiting
      */
     public void
-    setVoiceMessageWaiting(int line, int countWaiting)
-    {
+    setVoiceMessageWaiting(int line, int countWaiting) {
         if (line != 1) {
             // only profile 1 is supported
             return;
@@ -374,14 +357,14 @@
 
         countVoiceMessages = countWaiting;
 
-        phone.notifyMessageWaitingIndicator();
+        ((GSMPhone) phone).notifyMessageWaitingIndicator();
 
         try {
             if (efMWIS != null) {
                 // TS 51.011 10.3.45
 
                 // lsb of byte 0 is 'voicemail' status
-                efMWIS[0] = (byte)((efMWIS[0] & 0xfe) 
+                efMWIS[0] = (byte)((efMWIS[0] & 0xfe)
                                     | (countVoiceMessages == 0 ? 0 : 1));
 
                 // byte 1 is the number of voice messages waiting
@@ -393,17 +376,17 @@
                     efMWIS[1] = (byte) countWaiting;
                 }
 
-                phone.mSIMFileHandler.updateEFLinearFixed(
+                phone.getIccFileHandler().updateEFLinearFixed(
                     EF_MWIS, 1, efMWIS, null,
                     obtainMessage (EVENT_UPDATE_DONE, EF_MWIS));
-            } 
+            }
 
             if (efCPHS_MWI != null) {
                     // Refer CPHS4_2.WW6 B4.2.3
-                efCPHS_MWI[0] = (byte)((efCPHS_MWI[0] & 0xf0) 
+                efCPHS_MWI[0] = (byte)((efCPHS_MWI[0] & 0xf0)
                             | (countVoiceMessages == 0 ? 0x5 : 0xa));
 
-                phone.mSIMFileHandler.updateEFTransparent(
+                phone.getIccFileHandler().updateEFTransparent(
                     EF_VOICE_MAIL_INDICATOR_CPHS, efCPHS_MWI,
                     obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS));
             }
@@ -413,22 +396,6 @@
         }
     }
 
-    /** @return  true if there are messages waiting, false otherwise. */
-    public boolean getVoiceMessageWaiting()
-    {
-        return countVoiceMessages != 0;
-    }
-
-    /**
-     * Returns number of voice messages waiting, if available
-     * If not available (eg, on an older CPHS SIM) -1 is returned if 
-     * getVoiceMessageWaiting() is true
-     */
-    public int getCountVoiceMessages()
-    {
-        return countVoiceMessages;
-    }
-
     public boolean getVoiceCallForwardingFlag() {
         return callForwardingEnabled;
     }
@@ -439,7 +406,7 @@
 
         callForwardingEnabled = enable;
 
-        phone.notifyCallForwardingIndicator();
+        ((GSMPhone) phone).notifyCallForwardingIndicator();
 
         try {
             if (mEfCfis != null) {
@@ -453,7 +420,7 @@
                 // TODO: Should really update other fields in EF_CFIS, eg,
                 // dialing number.  We don't read or use it right now.
 
-                phone.mSIMFileHandler.updateEFLinearFixed(
+                phone.getIccFileHandler().updateEFLinearFixed(
                         EF_CFIS, 1, mEfCfis, null,
                         obtainMessage (EVENT_UPDATE_DONE, EF_CFIS));
             }
@@ -467,7 +434,7 @@
                             | CFF_UNCONDITIONAL_DEACTIVE);
                 }
 
-                phone.mSIMFileHandler.updateEFTransparent(
+                phone.getIccFileHandler().updateEFTransparent(
                         EF_CFF_CPHS, mEfCff,
                         obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS));
             }
@@ -496,8 +463,7 @@
     /** Returns the 5 or 6 digit MCC/MNC of the operator that
      *  provided the SIM card. Returns null of SIM is not yet ready
      */
-    String getSIMOperatorNumeric()
-    {
+    String getSIMOperatorNumeric() {
         if (imsi == null) {
             return null;
         }
@@ -517,17 +483,8 @@
 
         return imsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
     }
-
-    boolean getRecordsLoaded()
-    {
-        if (recordsToLoad == 0 && recordsRequested == true) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
+    
+     /**
      * If the timezone is not already set, set it based on the MCC of the SIM.
      * @param mcc Mobile Country Code of the SIM
      */
@@ -557,8 +514,7 @@
     }
 
     //***** Overridden from Handler
-    public void handleMessage(Message msg)
-    {
+    public void handleMessage(Message msg) {
         AsyncResult ar;
         AdnRecord adn;
 
@@ -573,19 +529,19 @@
 
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                 onRadioOffOrNotAvailable();
-            break;  
+            break;
 
             /* IO events */
             case EVENT_GET_IMSI_DONE:
                 isRecordLoadResponse = true;
-            
+
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception != null) {
                     Log.e(LOG_TAG, "Exception querying IMSI, Exception:" + ar.exception);
                     break;
-                } 
-                
+                }
+
                 imsi = (String) ar.result;
 
                 // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
@@ -594,11 +550,11 @@
                     Log.e(LOG_TAG, "invalid IMSI " + imsi);
                     imsi = null;
                 }
-                
+
                 Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxxxx");
-                phone.mSimCard.updateImsiConfiguration(imsi);
-                phone.mSimCard.broadcastSimStateChangedIntent(
-                        SimCard.INTENT_VALUE_SIM_IMSI, null);
+                ((GSMPhone) phone).mSimCard.updateImsiConfiguration(imsi);
+                ((GSMPhone) phone).mSimCard.broadcastSimStateChangedIntent(
+                        SimCard.INTENT_VALUE_ICC_IMSI, null);
 
                 int mcc = Integer.parseInt(imsi.substring(0, 3));
                 setTimezoneFromMccIfNeeded(mcc);
@@ -616,7 +572,7 @@
                 if (ar.exception == null) {
                     // Refer TS 51.011 Section 10.3.44 for content details
                     Log.d(LOG_TAG, "EF_MBI: " +
-                            SimUtils.bytesToHexString(data));
+                            IccUtils.bytesToHexString(data));
 
                     // Voice mail record number stored first
                     mailboxIndex = (int)data[0] & 0xff;
@@ -651,20 +607,20 @@
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception != null) {
-                
-                    Log.d(LOG_TAG, "Invalid or missing EF" 
+
+                    Log.d(LOG_TAG, "Invalid or missing EF"
                         + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? "[MAILBOX]" : "[MBDN]"));
 
                     // Bug #645770 fall back to CPHS
                     // FIXME should use SST to decide
 
                     if (msg.what == EVENT_GET_MBDN_DONE) {
-                        //load CPHS on fail... 
+                        //load CPHS on fail...
                         // FIXME right now, only load line1's CPHS voice mail entry
 
                         recordsToLoad += 1;
                         new AdnRecordLoader(phone).loadFromEF(
-                                EF_MAILBOX_CPHS, EF_EXT1, 1, 
+                                EF_MAILBOX_CPHS, EF_EXT1, 1,
                                 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
                     }
                     break;
@@ -672,7 +628,8 @@
 
                 adn = (AdnRecord)ar.result;
 
-                Log.d(LOG_TAG, "VM: " + adn + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? " EF[MAILBOX]" : " EF[MBDN]"));
+                Log.d(LOG_TAG, "VM: " + adn +
+                        ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? " EF[MAILBOX]" : " EF[MBDN]"));
 
                 if (adn.isEmpty() && msg.what == EVENT_GET_MBDN_DONE) {
                     // Bug #645770 fall back to CPHS
@@ -680,7 +637,7 @@
                     // FIXME right now, only load line1's CPHS voice mail entry
                     recordsToLoad += 1;
                     new AdnRecordLoader(phone).loadFromEF(
-                            EF_MAILBOX_CPHS, EF_EXT1, 1, 
+                            EF_MAILBOX_CPHS, EF_EXT1, 1,
                             obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
 
                     break;
@@ -730,7 +687,7 @@
                 }
 
                 Log.d(LOG_TAG, "EF_MWIS: " +
-                   SimUtils.bytesToHexString(data));
+                   IccUtils.bytesToHexString(data));
 
                 efMWIS = data;
 
@@ -744,11 +701,11 @@
                 countVoiceMessages = data[1] & 0xff;
 
                 if (voiceMailWaiting && countVoiceMessages == 0) {
-                    // Unknown count = -1 
+                    // Unknown count = -1
                     countVoiceMessages = -1;
                 }
 
-                phone.notifyMessageWaitingIndicator();
+                ((GSMPhone) phone).notifyMessageWaitingIndicator();
             break;
 
             case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
@@ -777,7 +734,7 @@
                         countVoiceMessages = 0;
                     }
 
-                    phone.notifyMessageWaitingIndicator();
+                    ((GSMPhone) phone).notifyMessageWaitingIndicator();
                 }
             break;
 
@@ -786,13 +743,13 @@
 
                 ar = (AsyncResult)msg.obj;
                 data = (byte[])ar.result;
-                
+
                 if (ar.exception != null) {
                     break;
-                }                
+                }
 
-                iccid = SimUtils.bcdToString(data, 0, data.length);
-            
+                iccid = IccUtils.bcdToString(data, 0, data.length);
+
                 Log.d(LOG_TAG, "iccid: " + iccid);
 
             break;
@@ -809,7 +766,7 @@
                 }
 
                 Log.d(LOG_TAG, "EF_AD: " +
-                    SimUtils.bytesToHexString(data));
+                    IccUtils.bytesToHexString(data));
 
                 if (data.length < 3) {
                     Log.d(LOG_TAG, "SIMRecords: Corrupt AD data on SIM");
@@ -851,14 +808,14 @@
                 }
 
                 Log.d(LOG_TAG, "EF_CFF_CPHS: " +
-                        SimUtils.bytesToHexString(data));
+                        IccUtils.bytesToHexString(data));
                 mEfCff = data;
 
                 if (mEfCfis == null) {
                     callForwardingEnabled =
                         ((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
 
-                    phone.notifyCallForwardingIndicator();
+                    ((GSMPhone) phone).notifyCallForwardingIndicator();
                 }
                 break;
 
@@ -872,7 +829,7 @@
                     break;
                 }
 
-                parseEfSpdi(data);                                
+                parseEfSpdi(data);
             break;
 
             case EVENT_UPDATE_DONE:
@@ -896,8 +853,8 @@
 
                 for ( ; tlv.isValidObject() ; tlv.nextObject()) {
                     if (tlv.getTag() == TAG_FULL_NETWORK_NAME) {
-                        pnnHomeName 
-                            = SimUtils.networkNameToString(
+                        pnnHomeName
+                            = IccUtils.networkNameToString(
                                 tlv.getData(), 0, tlv.getData().length);
                         break;
                     }
@@ -931,7 +888,8 @@
                             + ar.exception + " length " + index.length);
                 } else {
                     Log.d(LOG_TAG, "READ EF_SMS RECORD index=" + index[0]);
-                    phone.mSIMFileHandler.loadEFLinearFixed(EF_SMS,index[0],obtainMessage(EVENT_GET_SMS_DONE));
+                    phone.getIccFileHandler().loadEFLinearFixed(EF_SMS,index[0],
+                            obtainMessage(EVENT_GET_SMS_DONE));
                 }
                 break;
 
@@ -955,7 +913,7 @@
                     break;
                 }
 
-                //Log.d(LOG_TAG, "SST: " + SimUtils.bytesToHexString(data));
+                //Log.d(LOG_TAG, "SST: " + IccUtils.bytesToHexString(data));
             break;
 
             case EVENT_GET_INFO_CPHS_DONE:
@@ -969,7 +927,7 @@
 
                 mCphsInfo = (byte[])ar.result;
 
-                if (DBG) log("iCPHS: " + SimUtils.bytesToHexString(mCphsInfo));
+                if (DBG) log("iCPHS: " + IccUtils.bytesToHexString(mCphsInfo));
             break;
 
             case EVENT_SET_MBDN_DONE:
@@ -1050,20 +1008,20 @@
                 }
 
                 Log.d(LOG_TAG, "EF_CFIS: " +
-                   SimUtils.bytesToHexString(data));
+                   IccUtils.bytesToHexString(data));
 
                 mEfCfis = data;
                 
                 // Refer TS 51.011 Section 10.3.46 for the content description
                 callForwardingEnabled = ((data[1] & 0x01) != 0);
 
-                phone.notifyCallForwardingIndicator();
+                ((GSMPhone) phone).notifyCallForwardingIndicator();
                 break;
 
         }}catch (RuntimeException exc) {
             // I don't want these exceptions to be fatal
             Log.w(LOG_TAG, "Exception parsing SIM record", exc);
-        } finally {        
+        } finally {
             // Count up record load responses even if they are fails
             if (isRecordLoadResponse) {
                 onRecordLoaded();
@@ -1076,12 +1034,12 @@
             case EF_MBDN:
                 recordsToLoad++;
                 new AdnRecordLoader(phone).loadFromEF(EF_MBDN, EF_EXT6,
-                        mailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));            
+                        mailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
                 break;
             case EF_MAILBOX_CPHS:
                 recordsToLoad++;
                 new AdnRecordLoader(phone).loadFromEF(EF_MAILBOX_CPHS, EF_EXT1,
-                        1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));          
+                        1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
                 break;
             default:
                 // For now, fetch all records if this is not a
@@ -1093,7 +1051,7 @@
         }
     }
 
-    private void handleSimRefresh(int[] result) { 
+    private void handleSimRefresh(int[] result) {
         if (result == null || result.length == 0) {
 	    if (DBG) log("handleSimRefresh without input");
             return;
@@ -1102,7 +1060,7 @@
         switch ((result[0])) {
             case CommandsInterface.SIM_REFRESH_FILE_UPDATED:
  		if (DBG) log("handleSimRefresh with SIM_REFRESH_FILE_UPDATED");
-		// result[1] contains the EFID of the updated file.
+                // result[1] contains the EFID of the updated file.
                 int efid = result[1];
                 handleFileUpdate(efid);
                 break;
@@ -1130,8 +1088,7 @@
         }
     }
 
-    private void handleSms(byte[] ba)
-    {
+    private void handleSms(byte[] ba) {
         if (ba[0] != 0)
             Log.d("ENF", "status : " + ba[0]);
 
@@ -1142,15 +1099,11 @@
 
             // Note: Data may include trailing FF's.  That's OK; message
             // should still parse correctly.
-            byte[] nba = new byte[n - 1];
-            System.arraycopy(ba, 1, nba, 0, n - 1);
+            byte[] pdu = new byte[n - 1];
+            System.arraycopy(ba, 1, pdu, 0, n - 1);
+            SmsMessage message = SmsMessage.createFromPdu(pdu);
 
-            String pdu = SimUtils.bytesToHexString(nba);
-            // XXX first line is bogus
-            SmsMessage message = SmsMessage.newFromCMT(
-                                new String[] { "", pdu });
-
-            phone.mSMS.dispatchMessage(message);
+            ((GSMPhone) phone).mSMS.dispatchMessage(message);
         }
     }
 
@@ -1172,15 +1125,11 @@
 
                 // Note: Data may include trailing FF's.  That's OK; message
                 // should still parse correctly.
-                byte[] nba = new byte[n - 1];
-                System.arraycopy(ba, 1, nba, 0, n - 1);
+                byte[] pdu = new byte[n - 1];
+                System.arraycopy(ba, 1, pdu, 0, n - 1);
+                SmsMessage message = SmsMessage.createFromPdu(pdu);
 
-                String pdu = SimUtils.bytesToHexString(nba);
-                // XXX first line is bogus
-                SmsMessage message = SmsMessage.newFromCMT(
-                        new String[] { "", pdu });
-
-                phone.mSMS.dispatchMessage(message);
+                ((GSMPhone) phone).mSMS.dispatchMessage(message);
 
                 // 3GPP TS 51.011 v5.0.0 (20011-12)  10.5.3
                 // 1 == "received by MS from network; message read"
@@ -1188,18 +1137,14 @@
                 ba[0] = 1;
 
                 if (false) { // XXX writing seems to crash RdoServD
-                    phone.mSIMFileHandler.updateEFLinearFixed(EF_SMS, i, ba, null,
-                                    obtainMessage(EVENT_MARK_SMS_READ_DONE, i));
+                    phone.getIccFileHandler().updateEFLinearFixed(EF_SMS,
+                            i, ba, null, obtainMessage(EVENT_MARK_SMS_READ_DONE, i));
                 }
             }
         }
     }
 
-
-    //***** Private Methods
-
-    private void onRecordLoaded()
-    {
+    protected void onRecordLoaded() {
         // One record loaded successfully or failed, In either case
         // we need to update the recordsToLoad count
         recordsToLoad -= 1;
@@ -1211,21 +1156,19 @@
             recordsToLoad = 0;
         }
     }
-    
-    private void onAllRecordsLoaded()
-    {
+
+    protected void onAllRecordsLoaded() {
         Log.d(LOG_TAG, "SIMRecords: record load complete");
 
         String operator = getSIMOperatorNumeric();
 
         // Some fields require more than one SIM record to set
 
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_NUMERIC, operator);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
 
         if (imsi != null) {
-            phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ISO_COUNTRY,
-                                        MccTable.countryCodeForMcc(
-                                            Integer.parseInt(imsi.substring(0,3))));
+            phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
+                    MccTable.countryCodeForMcc(Integer.parseInt(imsi.substring(0,3))));
         }
         else {
             Log.e("SIM", "[SIMRecords] onAllRecordsLoaded: imsi is NULL!");
@@ -1236,16 +1179,19 @@
 
         recordsLoadedRegistrants.notifyRegistrants(
             new AsyncResult(null, null, null));
-        phone.mSimCard.broadcastSimStateChangedIntent(
-                SimCard.INTENT_VALUE_SIM_LOADED, null);
+        ((GSMPhone) phone).mSimCard.broadcastSimStateChangedIntent(
+                SimCard.INTENT_VALUE_ICC_LOADED, null);
     }
 
+    //***** Private methods
+
     private void setSpnFromConfig(String carrier) {
         if (mSpnOverride.containsCarrier(carrier)) {
             spn = mSpnOverride.getSpn(carrier);
         }
     }
 
+
     private void setVoiceMailByCountry (String spn) {
         if (mVmConfig.containsCarrier(spn)) {
             isVoiceMailFixed = true;
@@ -1258,22 +1204,22 @@
         /* broadcast intent SIM_READY here so that we can make sure
           READY is sent before IMSI ready
         */
-        phone.mSimCard.broadcastSimStateChangedIntent(
-                SimCard.INTENT_VALUE_SIM_READY, null);
+        ((GSMPhone) phone).mSimCard.broadcastSimStateChangedIntent(
+                SimCard.INTENT_VALUE_ICC_READY, null);
 
         fetchSimRecords();
     }
 
     private void fetchSimRecords() {
         recordsRequested = true;
+        IccFileHandler iccFh = phone.getIccFileHandler();
 
-	Log.v(LOG_TAG, "SIMRecords:fetchSimRecords " + recordsToLoad);
+        Log.v(LOG_TAG, "SIMRecords:fetchSimRecords " + recordsToLoad);
 
         phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_ICCID, 
-                            obtainMessage(EVENT_GET_ICCID_DONE));
+        iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
         recordsToLoad++;
 
         // FIXME should examine EF[MSISDN]'s capability configuration
@@ -1283,17 +1229,14 @@
         recordsToLoad++;
 
         // Record number is subscriber profile
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_MBI, 1, 
-                        obtainMessage(EVENT_GET_MBI_DONE));
+        iccFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_AD,  
-                        obtainMessage(EVENT_GET_AD_DONE));
+        iccFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
         recordsToLoad++;
 
         // Record number is subscriber profile
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_MWIS, 1, 
-                        obtainMessage(EVENT_GET_MWIS_DONE));
+        iccFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE));
         recordsToLoad++;
 
 
@@ -1301,50 +1244,49 @@
         // the same info as EF[MWIS]. If both exist, both are updated
         // but the EF[MWIS] data is preferred
         // Please note this must be loaded after EF[MWIS]
-        phone.mSIMFileHandler.loadEFTransparent(
-                EF_VOICE_MAIL_INDICATOR_CPHS, 
+        iccFh.loadEFTransparent(
+                EF_VOICE_MAIL_INDICATOR_CPHS,
                 obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE));
         recordsToLoad++;
 
         // Same goes for Call Forward Status indicator: fetch both
         // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred.
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));
+        iccFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));
         recordsToLoad++;
-        phone.mSIMFileHandler.loadEFTransparent(EF_CFF_CPHS,
-                obtainMessage(EVENT_GET_CFF_DONE));
+        iccFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE));
         recordsToLoad++;
 
 
         getSpnFsm(true, null);
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_SPDI, 
-            obtainMessage(EVENT_GET_SPDI_DONE));
+        iccFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_PNN, 1,
-            obtainMessage(EVENT_GET_PNN_DONE));
+        iccFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_SST,
-            obtainMessage(EVENT_GET_SST_DONE));
+        iccFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_INFO_CPHS,
-                obtainMessage(EVENT_GET_INFO_CPHS_DONE));
+        iccFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE));
         recordsToLoad++;
 
         // XXX should seek instead of examining them all
         if (false) { // XXX
-            phone.mSIMFileHandler.loadEFLinearFixedAll(EF_SMS,
-                obtainMessage(EVENT_GET_ALL_SMS_DONE));
+            iccFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE));
             recordsToLoad++;
         }
 
         if (CRASH_RIL) {
-            String sms = "0107912160130310f20404d0110041007030208054832b0120ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
-            byte[] ba = SimUtils.hexStringToBytes(sms);
+            String sms = "0107912160130310f20404d0110041007030208054832b0120"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "ffffffffffffffffffffffffffffff";
+            byte[] ba = IccUtils.hexStringToBytes(sms);
 
-            phone.mSIMFileHandler.updateEFLinearFixed(EF_SMS, 1, ba, null,
+            iccFh.updateEFLinearFixed(EF_SMS, 1, ba, null,
                             obtainMessage(EVENT_MARK_SMS_READ_DONE, 1));
         }
     }
@@ -1356,7 +1298,7 @@
      *
      * If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
      */
-    int getDisplayRule(String plmn) {
+    protected int getDisplayRule(String plmn) {
         int rule;
         if (spn == null || spnDisplayCondition == -1) {
             // EF_SPN was not found on the SIM, or not yet loaded.  Just show ONS.
@@ -1431,7 +1373,7 @@
             case INIT:
                 spn = null;
 
-                phone.mSIMFileHandler.loadEFTransparent( EF_SPN,
+                phone.getIccFileHandler().loadEFTransparent( EF_SPN,
                         obtainMessage(EVENT_GET_SPN_DONE));
                 recordsToLoad++;
 
@@ -1441,20 +1383,20 @@
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
                     spnDisplayCondition = 0xff & data[0];
-                    spn = SimUtils.adnStringFieldToString(data, 1, data.length - 1);
+                    spn = IccUtils.adnStringFieldToString(data, 1, data.length - 1);
 
                     if (DBG) log("Load EF_SPN: " + spn
                             + " spnDisplayCondition: " + spnDisplayCondition);
-                    phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, spn);
+                    phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
 
                     spnState = Get_Spn_Fsm_State.IDLE;
                 } else {
-                    phone.mSIMFileHandler.loadEFTransparent( EF_SPN_CPHS,
+                    phone.getIccFileHandler().loadEFTransparent( EF_SPN_CPHS,
                             obtainMessage(EVENT_GET_SPN_DONE));
                     recordsToLoad++;
 
                     spnState = Get_Spn_Fsm_State.READ_SPN_CPHS;
-                    
+
                     // See TS 51.011 10.3.11.  Basically, default to
                     // show PLMN always, and SPN also if roaming.
                     spnDisplayCondition = -1;
@@ -1463,16 +1405,16 @@
             case READ_SPN_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    spn = SimUtils.adnStringFieldToString(
+                    spn = IccUtils.adnStringFieldToString(
                             data, 0, data.length - 1 );
 
                     if (DBG) log("Load EF_SPN_CPHS: " + spn);
-                    phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, spn);
+                    phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
 
                     spnState = Get_Spn_Fsm_State.IDLE;
                 } else {
-                    phone.mSIMFileHandler.loadEFTransparent( EF_SPN_SHORT_CPHS,
-                            obtainMessage(EVENT_GET_SPN_DONE));
+                    phone.getIccFileHandler().loadEFTransparent(
+                            EF_SPN_SHORT_CPHS, obtainMessage(EVENT_GET_SPN_DONE));
                     recordsToLoad++;
 
                     spnState = Get_Spn_Fsm_State.READ_SPN_SHORT_CPHS;
@@ -1481,11 +1423,11 @@
             case READ_SPN_SHORT_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    spn = SimUtils.adnStringFieldToString(
+                    spn = IccUtils.adnStringFieldToString(
                             data, 0, data.length - 1);
 
                     if (DBG) log("Load EF_SPN_SHORT_CPHS: " + spn);
-                    phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, spn);
+                    phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
                 }else {
                     if (DBG) log("No SPN loaded in either CHPS or 3GPP");
                 }
@@ -1503,8 +1445,7 @@
      * are treated specially when determining SPN display
      */
     private void
-    parseEfSpdi(byte[] data)
-    {
+    parseEfSpdi(byte[] data) {
         SimTlv tlv = new SimTlv(data, 0, data.length);
 
         byte[] plmnEntries = null;
@@ -1524,8 +1465,8 @@
         spdiNetworks = new ArrayList<String>(plmnEntries.length / 3);
 
         for (int i = 0 ; i + 2 < plmnEntries.length ; i += 3) {
-            String plmnCode;        
-            plmnCode = SimUtils.bcdToString(plmnEntries, i, 3);
+            String plmnCode;
+            plmnCode = IccUtils.bcdToString(plmnEntries, i, 3);
 
             // Valid operator codes are 5 or 6 digits
             if (plmnCode.length() >= 5) {
@@ -1543,7 +1484,8 @@
         return ((mCphsInfo[1] & CPHS_SST_MBN_MASK) == CPHS_SST_MBN_ENABLED );
     }
 
-    private void log(String s) {
+    protected void log(String s) {
         Log.d(LOG_TAG, "[SIMRecords] " + s);
     }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
deleted file mode 100644
index 5585524..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.app.AlertDialog;
-import android.app.PendingIntent.CanceledException;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.DialogInterface;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.net.Uri;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Message;
-import android.os.PowerManager;
-import android.provider.Telephony;
-import android.provider.Settings;
-import android.provider.Telephony.Sms.Intents;
-import android.telephony.gsm.SmsMessage;
-import android.telephony.gsm.SmsManager;
-import com.android.internal.telephony.WapPushOverSms;
-import android.telephony.ServiceState;
-import android.util.Config;
-import com.android.internal.util.HexDump;
-import android.util.Log;
-import android.view.WindowManager;
-
-import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Random;
-
-import com.android.internal.R;
-
-final class SMSDispatcher extends Handler {
-    private static final String TAG = "GSM";
-
-    /** Default checking period for SMS sent without uesr permit */
-    private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000;
-
-    /** Default number of SMS sent in checking period without uesr permit */
-    private static final int DEFAULT_SMS_MAX_COUNT = 100;
-
-    /** Default timeout for SMS sent query */
-    private static final int DEFAULT_SMS_TIMOUEOUT = 6000;
-
-    private static final String[] RAW_PROJECTION = new String[] {
-        "pdu",
-        "sequence",
-    };
-
-    static final int MAIL_SEND_SMS = 1;
-
-    static final int EVENT_NEW_SMS = 1;
-
-    static final int EVENT_SEND_SMS_COMPLETE = 2;
-
-    /** Retry sending a previously failed SMS message */
-    static final int EVENT_SEND_RETRY = 3;
-
-    /** Status report received */
-    static final int EVENT_NEW_SMS_STATUS_REPORT = 5;
-
-    /** SIM storage is full */
-    static final int EVENT_SIM_FULL = 6;
-
-    /** SMS confirm required */
-    static final int EVENT_POST_ALERT = 7;
-
-    /** Send the user confirmed SMS */
-    static final int EVENT_SEND_CONFIRMED_SMS = 8;
-
-    /** Alert is timeout */
-    static final int EVENT_ALERT_TIMEOUT = 9;
-
-    private final GSMPhone mPhone;
-
-    private final WapPushOverSms mWapPush;
-
-    private final Context mContext;
-
-    private final ContentResolver mResolver;
-
-    private final CommandsInterface mCm;
-
-    private final Uri mRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw");
-
-    /** Maximum number of times to retry sending a failed SMS. */
-    private static final int MAX_SEND_RETRIES = 3;
-    /** Delay before next send attempt on a failed SMS, in milliseconds. */
-    private static final int SEND_RETRY_DELAY = 2000; 
-    /** single part SMS */
-    private static final int SINGLE_PART_SMS = 1;
-
-    /**
-     * Message reference for a CONCATENATED_8_BIT_REFERENCE or
-     * CONCATENATED_16_BIT_REFERENCE message set.  Should be
-     * incremented for each set of concatenated messages.
-     */
-    private static int sConcatenatedRef;
-
-    private SmsCounter mCounter;
-
-    private SmsTracker mSTracker;
-
-    /** Wake lock to ensure device stays awake while dispatching the SMS intent. */
-    private PowerManager.WakeLock mWakeLock;
-
-    /**
-     * Hold the wake lock for 5 seconds, which should be enough time for 
-     * any receiver(s) to grab its own wake lock.
-     */
-    private final int WAKE_LOCK_TIMEOUT = 5000;
-
-    /**
-     *  Implement the per-application based SMS control, which only allows
-     *  a limit on the number of SMS/MMS messages an app can send in checking
-     *  period.
-     */
-    private class SmsCounter {
-        private int mCheckPeriod;
-        private int mMaxAllowed;
-        private HashMap<String, ArrayList<Long>> mSmsStamp;
-
-        /**
-         * Create SmsCounter
-         * @param mMax is the number of SMS allowed without user permit
-         * @param mPeriod is the checking period
-         */
-        SmsCounter(int mMax, int mPeriod) {
-            mMaxAllowed = mMax;
-            mCheckPeriod = mPeriod;
-            mSmsStamp = new HashMap<String, ArrayList<Long>> ();
-        }
-
-        /**
-         * Check to see if an application allow to send new SMS messages
-         *  
-         * @param appName is the application sending sms
-         * @param smsWaiting is the number of new sms wants to be sent
-         * @return true if application is allowed to send the requested number 
-         *         of new sms messages 
-         */
-        boolean check(String appName, int smsWaiting) {
-            if (!mSmsStamp.containsKey(appName)) {
-                mSmsStamp.put(appName, new ArrayList<Long>());
-            }
-
-            return isUnderLimit(mSmsStamp.get(appName), smsWaiting);
-        }
-
-        private boolean isUnderLimit(ArrayList<Long> sent, int smsWaiting) {
-            Long ct =  System.currentTimeMillis();
-
-            Log.d(TAG, "SMS send size=" + sent.size() + "time=" + ct);
-
-            while (sent.size() > 0 && (ct - sent.get(0)) > mCheckPeriod ) {
-                    sent.remove(0);
-            }
-            
-            if ( (sent.size() + smsWaiting) <= mMaxAllowed) {
-                for (int i = 0; i < smsWaiting; i++ ) {
-                    sent.add(ct);
-                }
-                return true;
-            }
-            return false;
-        }
-    }
-
-    SMSDispatcher(GSMPhone phone) {
-        mPhone = phone;
-        mWapPush = new WapPushOverSms(phone);
-        mContext = phone.getContext();
-        mResolver = mContext.getContentResolver();
-        mCm = phone.mCM;
-        mSTracker = null;
-
-        createWakelock();
-
-        int check_period = Settings.Gservices.getInt(mResolver,
-                Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
-                DEFAULT_SMS_CHECK_PERIOD);
-        int max_count = Settings.Gservices.getInt(mResolver,
-                Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
-                DEFAULT_SMS_MAX_COUNT);
-        mCounter = new SmsCounter(max_count, check_period);
-
-        mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
-        mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
-        mCm.setOnSimSmsFull(this, EVENT_SIM_FULL, null);
-
-        // Don't always start message ref at 0.
-        sConcatenatedRef = new Random().nextInt(256);
-    }
-
-    /* TODO: Need to figure out how to keep track of status report routing in a
-     *       persistent manner. If the phone process restarts (reboot or crash),
-     *       we will lose this list and any status reports that come in after
-     *       will be dropped.
-     */
-    /** Sent messages awaiting a delivery status report. */
-    private final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>();
-
-    /**
-     * Handles events coming from the phone stack. Overridden from handler.
-     *
-     * @param msg the message to handle
-     */
-    @Override
-    public void handleMessage(Message msg) {
-        AsyncResult ar;
-
-        switch (msg.what) {
-        case EVENT_NEW_SMS:
-            // A new SMS has been received by the device
-            if (Config.LOGD) {
-                Log.d(TAG, "New SMS Message Received");
-            }
-
-            SmsMessage sms;
-
-            ar = (AsyncResult) msg.obj;
-
-            // FIXME unit test leaves cm == null. this should change
-            if (mCm != null) {
-                // FIXME only acknowledge on store
-                mCm.acknowledgeLastIncomingSMS(true, null);
-            }
-
-            if (ar.exception != null) {
-                Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception);
-                return;
-            }
-
-            sms = (SmsMessage) ar.result;
-            dispatchMessage(sms);
-
-            break;
-
-        case EVENT_SEND_SMS_COMPLETE:
-            // An outbound SMS has been sucessfully transferred, or failed.
-            handleSendComplete((AsyncResult) msg.obj);
-            break;
-
-        case EVENT_SEND_RETRY:
-            sendSms((SmsTracker) msg.obj);
-            break;
-
-        case EVENT_NEW_SMS_STATUS_REPORT:
-            handleStatusReport((AsyncResult)msg.obj);
-            break;
-
-        case EVENT_SIM_FULL:
-            handleSimFull();
-            break;
-
-        case EVENT_POST_ALERT:
-            handleReachSentLimit((SmsTracker)(msg.obj));
-            break;
-
-        case EVENT_ALERT_TIMEOUT:
-            ((AlertDialog)(msg.obj)).dismiss();
-            msg.obj = null;
-            mSTracker = null;
-            break;
-
-        case EVENT_SEND_CONFIRMED_SMS:
-            if (mSTracker!=null) {
-                if (isMultipartTracker(mSTracker)) {
-                    sendMultipartSms(mSTracker);
-                } else {
-                    sendSms(mSTracker);
-                } 
-                mSTracker = null;
-            }
-            break;
-        }
-    }
-
-    private void createWakelock() {
-        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SMSDispatcher");
-        mWakeLock.setReferenceCounted(true);
-    }
-
-    private void sendBroadcast(Intent intent, String permission) {
-        // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
-        // receivers time to take their own wake locks.
-        mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
-        mContext.sendBroadcast(intent, permission);
-    }
-
-    /**
-     * Called when SIM_FULL message is received from the RIL.  Notifies interested
-     * parties that SIM storage for SMS messages is full.
-     */
-    private void handleSimFull() {
-        // broadcast SIM_FULL intent
-        Intent intent = new Intent(Intents.SIM_FULL_ACTION);
-        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
-    }
-
-    /**
-     * Called when a status report is received.  This should correspond to
-     * a previously successful SEND.
-     *
-     * @param ar AsyncResult passed into the message handler.  ar.result should
-     *           be a String representing the status report PDU, as ASCII hex.
-     */
-    private void handleStatusReport(AsyncResult ar) {
-        String pduString = (String) ar.result;
-        SmsMessage sms = SmsMessage.newFromCDS(pduString);
-
-        if (sms != null) {
-            int messageRef = sms.messageRef;
-            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
-                SmsTracker tracker = deliveryPendingList.get(i);
-                if (tracker.mMessageRef == messageRef) {
-                    // Found it.  Remove from list and broadcast.
-                    deliveryPendingList.remove(i);
-                    PendingIntent intent = tracker.mDeliveryIntent;
-                    Intent fillIn = new Intent();
-                    fillIn.putExtra("pdu", SimUtils.hexStringToBytes(pduString));
-                    try {
-                        intent.send(mContext, Activity.RESULT_OK, fillIn);
-                    } catch (CanceledException ex) {}
-
-                    // Only expect to see one tracker matching this messageref
-                    break;
-                }
-            }
-        }
-
-        if (mCm != null) {
-            mCm.acknowledgeLastIncomingSMS(true, null);
-        }
-    }
-
-    /**
-     * Called when SMS send completes. Broadcasts a sentIntent on success.
-     * On failure, either sets up retries or broadcasts a sentIntent with
-     * the failure in the result code.
-     *
-     * @param ar AsyncResult passed into the message handler.  ar.result should
-     *           an SmsResponse instance if send was successful.  ar.userObj
-     *           should be an SmsTracker instance.
-     */
-    private void handleSendComplete(AsyncResult ar) {
-        SmsTracker tracker = (SmsTracker) ar.userObj;
-        PendingIntent sentIntent = tracker.mSentIntent;
-
-        if (ar.exception == null) {
-            if (Config.LOGD) {
-                Log.d(TAG, "SMS send complete. Broadcasting "
-                        + "intent: " + sentIntent);
-            }
-
-            if (tracker.mDeliveryIntent != null) {
-                // Expecting a status report.  Add it to the list.
-                int messageRef = ((SmsResponse)ar.result).messageRef;
-                tracker.mMessageRef = messageRef;
-                deliveryPendingList.add(tracker);
-            }
-
-            if (sentIntent != null) {
-                try {
-                    sentIntent.send(Activity.RESULT_OK);
-                } catch (CanceledException ex) {}
-            }
-        } else {
-            if (Config.LOGD) {
-                Log.d(TAG, "SMS send failed");
-            }
-
-            int ss = mPhone.getServiceState().getState();
-
-            if (ss != ServiceState.STATE_IN_SERVICE) {
-                handleNotInService(ss, tracker);
-            } else if ((((CommandException)(ar.exception)).getCommandError()
-                    == CommandException.Error.SMS_FAIL_RETRY) &&
-                   tracker.mRetryCount < MAX_SEND_RETRIES) {
-                // Retry after a delay if needed.
-                // TODO: According to TS 23.040, 9.2.3.6, we should resend
-                //       with the same TP-MR as the failed message, and
-                //       TP-RD set to 1.  However, we don't have a means of
-                //       knowing the MR for the failed message (EF_SMSstatus
-                //       may or may not have the MR corresponding to this
-                //       message, depending on the failure).  Also, in some
-                //       implementations this retry is handled by the baseband.
-                tracker.mRetryCount++;
-                Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
-                sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
-            } else if (tracker.mSentIntent != null) {
-                // Done retrying; return an error to the app.
-                try {
-                    tracker.mSentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
-                } catch (CanceledException ex) {}
-            }
-        }
-    }
-
-    /**
-     * Handles outbound message when the phone is not in service.
-     *
-     * @param ss     Current service state.  Valid values are:
-     *                  OUT_OF_SERVICE
-     *                  EMERGENCY_ONLY
-     *                  POWER_OFF
-     * @param tracker   An SmsTracker for the current message.
-     */
-    private void handleNotInService(int ss, SmsTracker tracker) {
-        if (tracker.mSentIntent != null) {
-            try {
-                if (ss == ServiceState.STATE_POWER_OFF) {
-                    tracker.mSentIntent.send(SmsManager.RESULT_ERROR_RADIO_OFF);
-                } else {
-                    tracker.mSentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
-                }
-            } catch (CanceledException ex) {}
-        }
-    }
-
-    /**
-     * Dispatches an incoming SMS messages.
-     *
-     * @param sms the incoming message from the phone
-     */
-    /* package */ void dispatchMessage(SmsMessage sms) {
-
-        // If sms is null, means there was a parsing error.
-        // TODO: Should NAK this.
-        if (sms == null) {
-            return;
-        }
-
-        boolean handled = false;
-
-        // Special case the message waiting indicator messages
-        if (sms.isMWISetMessage()) {
-            mPhone.updateMessageWaitingIndicator(true);
-
-            if (sms.isMwiDontStore()) {
-                handled = true;
-            }
-
-            if (Config.LOGD) {
-                Log.d(TAG,
-                        "Received voice mail indicator set SMS shouldStore="
-                         + !handled);
-            }
-        } else if (sms.isMWIClearMessage()) {
-            mPhone.updateMessageWaitingIndicator(false);
-
-            if (sms.isMwiDontStore()) {
-                handled = true;
-            }
-
-            if (Config.LOGD) {
-                Log.d(TAG,
-                        "Received voice mail indicator clear SMS shouldStore="
-                        + !handled);
-            }
-        }
-
-        if (handled) {
-            return;
-        }
-
-        // Parse the headers to see if this is partial, or port addressed
-        int referenceNumber = -1;
-        int count = 0;
-        int sequence = 0;
-        int destPort = -1;
-
-        SmsHeader header = sms.getUserDataHeader();
-        if (header != null) {
-            for (SmsHeader.Element element : header.getElements()) {
-                try {
-                    switch (element.getID()) {
-                        case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
-                            byte[] data = element.getData();
-                            
-                            referenceNumber = data[0] & 0xff;
-                            count = data[1] & 0xff;
-                            sequence = data[2] & 0xff;
-                            
-                            // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
-                            // is zero, or sequence > count, ignore the entire element
-                            if (count == 0 || sequence == 0 || sequence > count) {
-                                referenceNumber = -1;
-                            }
-                            break;
-                        }
-                        
-                        case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
-                            byte[] data = element.getData();
-                            
-                            referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
-                            count = data[2] & 0xff;
-                            sequence = data[3] & 0xff;
-                            
-                            // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
-                            // is zero, or sequence > count, ignore the entire element
-                            if (count == 0 || sequence == 0 || sequence > count) {
-                                referenceNumber = -1;
-                            }
-                            break;
-                        }
-                        
-                        case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
-                            byte[] data = element.getData();
-                            
-                            destPort = (data[0] & 0xff) << 8;
-                            destPort |= (data[1] & 0xff);
-                            
-                            break;
-                        }
-                    }
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    Log.e(TAG, "Bad element in header", e);
-                    return;  // TODO: NACK the message or something, don't just discard.
-                }
-            }
-        }
-
-        if (referenceNumber == -1) {
-            // notify everyone of the message if it isn't partial
-            byte[][] pdus = new byte[1][];
-            pdus[0] = sms.getPdu();
-
-            if (destPort != -1) {
-                if (destPort == SmsHeader.PORT_WAP_PUSH) {
-                    mWapPush.dispatchWapPdu(sms.getUserData());
-                }
-                // The message was sent to a port, so concoct a URI for it
-                dispatchPortAddressedPdus(pdus, destPort);
-            } else {
-                // It's a normal message, dispatch it
-                dispatchPdus(pdus);
-            }
-        } else {
-            // Process the message part
-            processMessagePart(sms, referenceNumber, sequence, count, destPort);
-        }
-    }
-
-    /**
-     * If this is the last part send the parts out to the application, otherwise
-     * the part is stored for later processing.
-     */
-    private void processMessagePart(SmsMessage sms, int referenceNumber,
-            int sequence, int count, int destinationPort) {
-        // Lookup all other related parts
-        StringBuilder where = new StringBuilder("reference_number =");
-        where.append(referenceNumber);
-        where.append(" AND address = ?");
-        String[] whereArgs = new String[] {sms.getOriginatingAddress()};
-
-        byte[][] pdus = null;
-        Cursor cursor = null;
-        try {
-            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
-            int cursorCount = cursor.getCount();
-            if (cursorCount != count - 1) {
-                // We don't have all the parts yet, store this one away
-                ContentValues values = new ContentValues();
-                values.put("date", new Long(sms.getTimestampMillis()));
-                values.put("pdu", HexDump.toHexString(sms.getPdu()));
-                values.put("address", sms.getOriginatingAddress());
-                values.put("reference_number", referenceNumber);
-                values.put("count", count);
-                values.put("sequence", sequence);
-                if (destinationPort != -1) {
-                    values.put("destination_port", destinationPort);
-                }
-                mResolver.insert(mRawUri, values);
-
-                return;
-            }
-
-            // All the parts are in place, deal with them
-            int pduColumn = cursor.getColumnIndex("pdu");
-            int sequenceColumn = cursor.getColumnIndex("sequence");
-
-            pdus = new byte[count][];
-            for (int i = 0; i < cursorCount; i++) {
-                cursor.moveToNext();
-                int cursorSequence = (int)cursor.getLong(sequenceColumn);
-                pdus[cursorSequence - 1] = HexDump.hexStringToByteArray(
-                        cursor.getString(pduColumn));
-            }
-            // This one isn't in the DB, so add it
-            pdus[sequence - 1] = sms.getPdu();
-
-            // Remove the parts from the database
-            mResolver.delete(mRawUri, where.toString(), whereArgs);
-        } catch (SQLException e) {
-            Log.e(TAG, "Can't access multipart SMS database", e);
-            return;  // TODO: NACK the message or something, don't just discard.
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-
-        // Dispatch the PDUs to applications
-        switch (destinationPort) {
-        case SmsHeader.PORT_WAP_PUSH: {
-            // Build up the data stream
-            ByteArrayOutputStream output = new ByteArrayOutputStream();
-            for (int i = 0; i < count; i++) {
-                SmsMessage msg = SmsMessage.createFromPdu(pdus[i]);
-                byte[] data = msg.getUserData();
-                output.write(data, 0, data.length);
-            }
-
-            // Handle the PUSH
-            mWapPush.dispatchWapPdu(output.toByteArray());
-            break;
-        }
-
-        case -1:
-            // The messages were not sent to a port
-            dispatchPdus(pdus);
-            break;
-
-        default:
-            // The messages were sent to a port, so concoct a URI for it
-            dispatchPortAddressedPdus(pdus, destinationPort);
-            break;
-        }
-    }
-
-    /**
-     * Dispatches standard PDUs to interested applications
-     *
-     * @param pdus The raw PDUs making up the message
-     */
-    private void dispatchPdus(byte[][] pdus) {
-        Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
-        intent.putExtra("pdus", pdus);
-        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
-    }
-
-    /**
-     * Dispatches port addressed PDUs to interested applications
-     *
-     * @param pdus The raw PDUs making up the message
-     * @param port The destination port of the messages
-     */
-    private void dispatchPortAddressedPdus(byte[][] pdus, int port) {
-        Uri uri = Uri.parse("sms://localhost:" + port);
-        Intent intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);
-        intent.putExtra("pdus", pdus);
-        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
-    }
-
-
-    /**
-     * Send a multi-part text based SMS.
-     *
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
-     *   the current default SMSC
-     * @param parts an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been sent.
-     *   The result code will be <code>Activity.RESULT_OK<code> for success,
-     *   or one of these errors:
-     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *   <code>RESULT_ERROR_RADIO_OFF</code>
-     *   <code>RESULT_ERROR_NULL_PDU</code>.
-     *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
-     *  which cause smaller number of SMS to be sent in checking period.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been delivered
-     *   to the recipient.  The raw pdu of the status report is in the
-     *   extended data ("pdu").
-     */
-    void sendMultipartText(String destinationAddress, String scAddress, ArrayList<String> parts,
-            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
-
-        PendingIntent sentIntent = null;
-        
-        
-        int ss = mPhone.getServiceState().getState();
-        
-        if (ss == ServiceState.STATE_IN_SERVICE) {
-            // Only check SMS sending limit while in service
-            if (sentIntents != null && sentIntents.size() > 0) {
-                sentIntent = sentIntents.get(0);
-            }
-            String appName = getAppNameByIntent(sentIntent);
-            if ( !mCounter.check(appName, parts.size())) {
-                HashMap<String, Object> map = new HashMap<String, Object>();
-                map.put("destination", destinationAddress);
-                map.put("scaddress", scAddress);
-                map.put("parts", parts);
-                map.put("sentIntents", sentIntents);
-                map.put("deliveryIntents", deliveryIntents);
-                
-                SmsTracker multipartParameter = new SmsTracker(map, null, null);
-
-                sendMessage(obtainMessage(EVENT_POST_ALERT, multipartParameter));
-                return;
-            }
-        }
-        
-        sendMultipartTextWithPermit(destinationAddress, 
-                scAddress, parts, sentIntents, deliveryIntents);
-    }
-
-    /**
-     * Send a multi-part text based SMS which already passed SMS control check.
-     *
-     * It is the working function for sendMultipartText().
-     * 
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
-     *   the current default SMSC
-     * @param parts an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been sent.
-     *   The result code will be <code>Activity.RESULT_OK<code> for success,
-     *   or one of these errors:
-     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *   <code>RESULT_ERROR_RADIO_OFF</code>
-     *   <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been delivered
-     *   to the recipient.  The raw pdu of the status report is in the
-     *   extended data ("pdu").
-     */
-    private void sendMultipartTextWithPermit(String destinationAddress, 
-            String scAddress, ArrayList<String> parts,
-            ArrayList<PendingIntent> sentIntents, 
-            ArrayList<PendingIntent> deliveryIntents) {
-        
-        PendingIntent sentIntent = null;
-        PendingIntent deliveryIntent = null;
-        
-        // check if in service
-        int ss = mPhone.getServiceState().getState();
-        if (ss != ServiceState.STATE_IN_SERVICE) {
-            for (int i = 0, count = parts.size(); i < count; i++) {
-                if (sentIntents != null && sentIntents.size() > i) {
-                    sentIntent = sentIntents.get(i);
-                }
-                SmsTracker tracker = new SmsTracker(null, sentIntent, null);
-                handleNotInService(ss, tracker);
-            }
-            return;
-        }
-
-        int ref = ++sConcatenatedRef & 0xff;
-
-        for (int i = 0, count = parts.size(); i < count; i++) {
-            // build SmsHeader
-            byte[] data = new byte[3];
-            data[0] = (byte) ref;   // reference #, unique per message
-            data[1] = (byte) count; // total part count
-            data[2] = (byte) (i + 1);  // 1-based sequence
-            SmsHeader header = new SmsHeader();
-            header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
- 
-            if (sentIntents != null && sentIntents.size() > i) {
-                sentIntent = sentIntents.get(i);
-            }
-            if (deliveryIntents != null && deliveryIntents.size() > i) {
-                deliveryIntent = deliveryIntents.get(i);
-            }
-
-            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
-                    parts.get(i), deliveryIntent != null, header.toByteArray());
-
-            HashMap<String, Object> map = new HashMap<String, Object>();
-            map.put("smsc", pdus.encodedScAddress);
-            map.put("pdu", pdus.encodedMessage);
-
-            SmsTracker tracker = new SmsTracker(map, sentIntent,
-                    deliveryIntent);
-            sendSms(tracker);
-        }        
-    }
-
-    /**
-     * Send a SMS
-     *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  defatult SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
-     *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
-     *  which cause smaller number of SMS to be sent in checking period.
-     * @param deliveryIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is delivered to the recipient.  The
-     *  raw pdu of the status report is in the extended data ("pdu").
-     */
-    void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        if (pdu == null) {
-            if (sentIntent != null) {
-                try {
-                    sentIntent.send(SmsManager.RESULT_ERROR_NULL_PDU);
-                } catch (CanceledException ex) {}
-            }
-            return;
-        }
-
-        HashMap<String, Object> map = new HashMap<String, Object>();
-        map.put("smsc", smsc);
-        map.put("pdu", pdu);
-
-        SmsTracker tracker = new SmsTracker(map, sentIntent,
-                deliveryIntent);
-        int ss = mPhone.getServiceState().getState();
-
-        if (ss != ServiceState.STATE_IN_SERVICE) {
-            handleNotInService(ss, tracker);
-        } else {
-            String appName = getAppNameByIntent(sentIntent);
-            if (mCounter.check(appName, SINGLE_PART_SMS)) {
-                sendSms(tracker);
-            } else {
-                sendMessage(obtainMessage(EVENT_POST_ALERT, tracker));
-            }
-        }
-    }
-
-    /**
-     * Post an alert while SMS needs user confirm.
-     *
-     * An SmsTracker for the current message.
-     */
-    private void handleReachSentLimit(SmsTracker tracker) {
-
-        Resources r = Resources.getSystem();
-
-        String appName = getAppNameByIntent(tracker.mSentIntent);
-
-        AlertDialog d = new AlertDialog.Builder(mContext)
-                .setTitle(r.getString(R.string.sms_control_title))
-                .setMessage(appName + " " + r.getString(R.string.sms_control_message))
-                .setPositiveButton(r.getString(R.string.sms_control_yes), mListener)
-                .setNegativeButton(r.getString(R.string.sms_control_no), null)
-                .create();
-
-        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-        d.show();
-
-        mSTracker = tracker;
-        sendMessageDelayed ( obtainMessage(EVENT_ALERT_TIMEOUT, d),
-                DEFAULT_SMS_TIMOUEOUT);
-    }
-
-    private String getAppNameByIntent(PendingIntent intent) {
-        Resources r = Resources.getSystem();
-        return (intent != null) ? intent.getTargetPackage()
-            : r.getString(R.string.sms_control_default_app_name);
-    }
-
-    /**
-     * Send the message along to the radio.
-     *
-     * @param tracker holds the SMS message to send
-     */
-    private void sendSms(SmsTracker tracker) {
-        HashMap map = tracker.mData;
-
-        byte smsc[] = (byte[]) map.get("smsc");
-        byte pdu[] = (byte[]) map.get("pdu");
-
-        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
-        mCm.sendSMS(SimUtils.bytesToHexString(smsc),
-                SimUtils.bytesToHexString(pdu), reply);
-    }
-
-    /**
-     * Send the multi-part SMS based on multipart Sms tracker
-     * 
-     * @param tracker holds the multipart Sms tracker ready to be sent
-     */
-    private void sendMultipartSms (SmsTracker tracker) {
-        ArrayList<String> parts;
-        ArrayList<PendingIntent> sentIntents;
-        ArrayList<PendingIntent> deliveryIntents;
-        
-        HashMap map = tracker.mData;
-        
-        String destinationAddress = (String) map.get("destination");
-        String scAddress = (String) map.get("scaddress");
-        
-        parts = (ArrayList<String>) map.get("parts");
-        sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents");
-        deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents");
-     
-        sendMultipartTextWithPermit(destinationAddress, 
-                scAddress, parts, sentIntents, deliveryIntents);
-
-    }
-    
-    /**
-     * Check if a SmsTracker holds multi-part Sms
-     * 
-     * @param tracker a SmsTracker could hold a multi-part Sms
-     * @return true for tracker holds Multi-parts Sms
-     */
-    private boolean isMultipartTracker (SmsTracker tracker) {
-        HashMap map = tracker.mData;
-        return ( map.get("parts") != null);
-    }
-    
-    /**
-     * Keeps track of an SMS that has been sent to the RIL, until it it has
-     * successfully been sent, or we're done trying.
-     *
-     */
-    static class SmsTracker {
-        HashMap mData;
-        int mRetryCount;
-        int mMessageRef;
-
-        PendingIntent mSentIntent;
-        PendingIntent mDeliveryIntent;
-
-        SmsTracker(HashMap data, PendingIntent sentIntent,
-                PendingIntent deliveryIntent) {
-            mData = data;
-            mSentIntent = sentIntent;
-            mDeliveryIntent = deliveryIntent;
-            mRetryCount = 0;
-        }
-
-    }
-
-    private DialogInterface.OnClickListener mListener =
-            new DialogInterface.OnClickListener() {
-
-                public void onClick(DialogInterface dialog, int which) {
-                    if (which == DialogInterface.BUTTON_POSITIVE) {
-                        Log.d(TAG, "click YES to send out sms");
-                        sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS));
-                    }
-                }
-            };
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
similarity index 86%
rename from telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
rename to telephony/java/com/android/internal/telephony/gsm/SimCard.java
index a4cded9..9af3aa6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.telephony.gsm;
 
+import android.app.ActivityManagerNative;
+import android.content.Intent;
+import android.content.res.Configuration;
 import android.os.AsyncResult;
 import android.os.RemoteException;
 import android.os.Handler;
@@ -23,32 +26,34 @@
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.util.Log;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyProperties;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.TelephonyIntents;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.app.ActivityManagerNative;
+import com.android.internal.telephony.TelephonyProperties;
 
 import static android.Manifest.permission.READ_PHONE_STATE;
 
 /**
+ * Note: this class shares common code with RuimCard, consider a base class to minimize code
+ * duplication.
  * {@hide}
  */
-public final class GsmSimCard extends Handler implements SimCard {
+public final class SimCard extends Handler implements IccCard {
     static final String LOG_TAG="GSM";
-    
+
     //***** Instance Variables
     private static final boolean DBG = true;
 
     private GSMPhone phone;
-    private CommandsInterface.SimStatus status = null;
+    private CommandsInterface.IccStatus status = null;
+    private boolean mDesiredPinLocked;
+    private boolean mDesiredFdnEnabled;
     private boolean mSimPinLocked = true; // Default to locked
     private boolean mSimFdnEnabled = false; // Default to disabled.
                                             // Will be updated when SIM_READY.
-    private boolean mDesiredPinLocked;
-    private boolean mDesiredFdnEnabled;
 
     //***** Constants
 
@@ -72,8 +77,7 @@
 
     //***** Constructor
 
-    GsmSimCard(GSMPhone phone)
-    {
+    SimCard(GSMPhone phone) {
         this.phone = phone;
 
         phone.mCM.registerForSIMLockedOrAbsent(
@@ -87,12 +91,22 @@
 
         updateStateProperty();
     }
-    
+
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForSIMLockedOrAbsent(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        phone.mCM.unregisterForSIMReady(this);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SimCard finalized");
+    }
+
     //***** SimCard implementation
 
     public State
-    getState()
-    {
+    getState() {
         if (status == null) {
             switch(phone.mCM.getRadioState()) {
                 /* This switch block must not return anything in
@@ -111,12 +125,12 @@
             }
         } else {
             switch (status) {
-                case SIM_ABSENT:            return State.ABSENT;
-                case SIM_NOT_READY:         return State.UNKNOWN;
-                case SIM_READY:             return State.READY;
-                case SIM_PIN:               return State.PIN_REQUIRED;
-                case SIM_PUK:               return State.PUK_REQUIRED;
-                case SIM_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
+                case ICC_ABSENT:            return State.ABSENT;
+                case ICC_NOT_READY:         return State.UNKNOWN;
+                case ICC_READY:             return State.READY;
+                case ICC_PIN:               return State.PIN_REQUIRED;
+                case ICC_PUK:               return State.PUK_REQUIRED;
+                case ICC_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
             }
         }
 
@@ -129,8 +143,7 @@
     private RegistrantList networkLockedRegistrants = new RegistrantList();
 
 
-    public void registerForAbsent(Handler h, int what, Object obj)
-    {
+    public void registerForAbsent(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         absentRegistrants.add(r);
@@ -139,9 +152,9 @@
             r.notifyRegistrant();
         }
     }
-    
+
     public void unregisterForAbsent(Handler h) {
-    	absentRegistrants.remove(h);
+        absentRegistrants.remove(h);
     }
 
     public void registerForNetworkLocked(Handler h, int what, Object obj) {
@@ -155,11 +168,10 @@
     }
 
     public void unregisterForNetworkLocked(Handler h) {
-    	networkLockedRegistrants.remove(h);
+        networkLockedRegistrants.remove(h);
     }
-    
-    public void registerForLocked(Handler h, int what, Object obj)
-    {
+
+    public void registerForLocked(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         pinLockedRegistrants.add(r);
@@ -169,50 +181,44 @@
         }
     }
 
-    public void unregisterForLocked(Handler h)
-    {
+    public void unregisterForLocked(Handler h) {
         pinLockedRegistrants.remove(h);
     }
 
 
-    public void supplyPin (String pin, Message onComplete)
-    {
-        phone.mCM.supplySimPin(pin, 
+    public void supplyPin (String pin, Message onComplete) {
+        phone.mCM.supplyIccPin(pin,
                             obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyPuk (String puk, String newPin, Message onComplete)
-    {
-        phone.mCM.supplySimPuk(puk, newPin,
+    public void supplyPuk (String puk, String newPin, Message onComplete) {
+        phone.mCM.supplyIccPuk(puk, newPin,
                         obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPin2 (String pin2, Message onComplete)
-    {
-        phone.mCM.supplySimPin2(pin2, 
+    public void supplyPin2 (String pin2, Message onComplete) {
+        phone.mCM.supplyIccPin2(pin2,
                         obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPuk2 (String puk2, String newPin2, Message onComplete)
-    {
-        phone.mCM.supplySimPuk2(puk2, newPin2,
+    public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
+        phone.mCM.supplyIccPuk2(puk2, newPin2,
                 obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyNetworkDepersonalization (String pin, Message onComplete)
-    {
+    public void supplyNetworkDepersonalization (String pin, Message onComplete) {
         if(DBG) log("Network Despersonalization: " + pin);
         phone.mCM.supplyNetworkDepersonalization(pin,
                         obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public boolean getSimLockEnabled() {
+    public boolean getIccLockEnabled() {
        return mSimPinLocked;
     }
 
-    public boolean getSimFdnEnabled() {
+    public boolean getIccFdnEnabled() {
        return mSimFdnEnabled;
     }
 
-    public void setSimLockEnabled (boolean enabled,
+    public void setIccLockEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -226,7 +232,7 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
     }
 
-    public void setSimFdnEnabled (boolean enabled,
+    public void setIccFdnEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -241,18 +247,18 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
     }
 
-    public void changeSimLockPassword(String oldPassword, String newPassword,
+    public void changeIccLockPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin1 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin(oldPassword, newPassword,
+        phone.mCM.changeIccPin(oldPassword, newPassword,
                 obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
 
     }
 
-    public void changeSimFdnPassword(String oldPassword, String newPassword,
+    public void changeIccFdnPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin2 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin2(oldPassword, newPassword,
+        phone.mCM.changeIccPin2(oldPassword, newPassword,
                 obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
 
     }
@@ -275,11 +281,11 @@
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                 status = null;
                 updateStateProperty();
-                broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_NOT_READY, null);
+                broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_NOT_READY, null);
                 break;
             case EVENT_SIM_READY:
                 //TODO: put facility read in SIM_READY now, maybe in REG_NW
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
@@ -288,7 +294,7 @@
                         obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
                 break;
             case EVENT_SIM_LOCKED_OR_ABSENT:
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
@@ -306,7 +312,7 @@
                 // TODO should abstract these exceptions
                 AsyncResult.forMessage(((Message)ar.userObj)).exception
                                                     = ar.exception;
-                phone.mCM.getSimStatus(
+                phone.mCM.getIccStatus(
                     obtainMessage(EVENT_REPOLL_STATUS_DONE, ar.userObj));
                 break;
             case EVENT_REPOLL_STATUS_DONE:
@@ -415,24 +421,24 @@
     private void
     getSimStatusDone(AsyncResult ar) {
         if (ar.exception != null) {
-            Log.e(LOG_TAG,"Error getting SIM status. "
-                    + "RIL_REQUEST_GET_SIM_STATUS should "
+            Log.e(LOG_TAG,"Error getting ICC status. "
+                    + "RIL_REQUEST_GET_ICC_STATUS should "
                     + "never return an error", ar.exception);
             return;
         }
 
-        CommandsInterface.SimStatus newStatus 
-            = (CommandsInterface.SimStatus)  ar.result;
+        CommandsInterface.IccStatus newStatus
+            = (CommandsInterface.IccStatus)  ar.result;
 
         handleSimStatus(newStatus);
     }
 
     private void
-    handleSimStatus(CommandsInterface.SimStatus newStatus) {
+    handleSimStatus(CommandsInterface.IccStatus newStatus) {
         boolean transitionedIntoPinLocked;
         boolean transitionedIntoAbsent;
         boolean transitionedIntoNetworkLocked;
-        
+
         SimCard.State oldState, newState;
 
         oldState = getState();
@@ -451,17 +457,17 @@
         if (transitionedIntoPinLocked) {
             if(DBG) log("Notify SIM pin or puk locked.");
             pinLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED, 
+            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_LOCKED,
                     (newState == State.PIN_REQUIRED) ?
                        INTENT_VALUE_LOCKED_ON_PIN : INTENT_VALUE_LOCKED_ON_PUK);
         } else if (transitionedIntoAbsent) {
             if(DBG) log("Notify SIM missing.");
             absentRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_ABSENT, null);
+            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_ABSENT, null);
         } else if (transitionedIntoNetworkLocked) {
             if(DBG) log("Notify SIM network locked.");
             networkLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED,
+            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_LOCKED,
                   INTENT_VALUE_LOCKED_NETWORK);
         }
     }
@@ -469,7 +475,7 @@
     public void broadcastSimStateChangedIntent(String value, String reason) {
         Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         intent.putExtra(Phone.PHONE_NAME_KEY, phone.getPhoneName());
-        intent.putExtra(SimCard.INTENT_KEY_SIM_STATE, value);
+        intent.putExtra(SimCard.INTENT_KEY_ICC_STATE, value);
         intent.putExtra(SimCard.INTENT_KEY_LOCKED_REASON, reason);
         if(DBG) log("Broadcasting intent SIM_STATE_CHANGED_ACTION " +  value
                 + " reason " + reason);
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimConstants.java b/telephony/java/com/android/internal/telephony/gsm/SimConstants.java
deleted file mode 100644
index a7e3bbc..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/SimConstants.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-/**
- * {@hide}
- */
-public interface SimConstants {
-    // SIM file ids from TS 51.011
-    public static final int EF_ADN = 0x6F3A;
-    public static final int EF_FDN = 0x6F3B;
-    public static final int EF_SDN = 0x6F49;
-    public static final int EF_EXT1 = 0x6F4A;
-    public static final int EF_EXT2 = 0x6F4B;
-    public static final int EF_EXT3 = 0x6F4C;
-    public static final int EF_EXT6 = 0x6fc8;   // Ext record for EF[MBDN]
-    public static final int EF_MWIS = 0x6FCA;
-    public static final int EF_MBDN = 0x6fc7;
-    public static final int EF_PNN = 0x6fc5;
-    public static final int EF_SPN = 0x6F46;
-    public static final int EF_SMS = 0x6F3C;
-    public static final int EF_ICCID = 0x2fe2;
-    public static final int EF_AD = 0x6FAD;
-    public static final int EF_MBI = 0x6fc9;
-    public static final int EF_MSISDN = 0x6f40;
-    public static final int EF_SPDI = 0x6fcd;
-    public static final int EF_SST = 0x6f38;
-    public static final int EF_CFIS = 0x6FCB;
-    public static final int EF_IMG = 0x4f20;
-
-    // SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
-    public static final int EF_MAILBOX_CPHS = 0x6F17;
-    public static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
-    public static final int EF_CFF_CPHS = 0x6F13;
-    public static final int EF_SPN_CPHS = 0x6f14;
-    public static final int EF_SPN_SHORT_CPHS = 0x6f18;
-    public static final int EF_INFO_CPHS = 0x6f16;
-
-    // SMS record length from TS 51.011 10.5.3
-    static public final int SMS_RECORD_LENGTH = 176;
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimException.java b/telephony/java/com/android/internal/telephony/gsm/SimException.java
deleted file mode 100644
index 1c0daba..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/SimException.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-/**
- * {@hide}
- */
-public class SimException extends Exception
-{
-    SimException()
-    {
-
-    }
-
-    SimException(String s)
-    {
-        super(s);
-    }
-}
-
-final class SimVmFixedException extends SimException {
-    SimVmFixedException()
-    {
-
-    }
-
-    SimVmFixedException(String s)
-    {
-        super(s);
-    }    
-}
-
-final class SimVmNotSupportedException extends SimException {
-    SimVmNotSupportedException()
-    {
-
-    }
-
-    SimVmNotSupportedException(String s)
-    {
-        super(s);
-    }    
-}
-
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileNotFound.java b/telephony/java/com/android/internal/telephony/gsm/SimFileNotFound.java
deleted file mode 100644
index 982e2fd..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileNotFound.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-/**
- * {@hide}
- */
-public class SimFileNotFound extends SimException
-{
-    SimFileNotFound()
-    {
-
-    }
-
-    SimFileNotFound(String s)
-    {
-        super(s);
-    }
-
-    SimFileNotFound(int ef)
-    {
-        super("SIM EF Not Found 0x" + Integer.toHexString(ef));
-    }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
index 7cc9a80..076da6b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
@@ -25,6 +25,11 @@
 import android.telephony.PhoneNumberUtils;
 import android.util.Log;
 
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.PhoneProxy;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -32,247 +37,65 @@
  * SimPhoneBookInterfaceManager to provide an inter-process communication to
  * access ADN-like SIM records.
  */
-public class SimPhoneBookInterfaceManager extends ISimPhoneBook.Stub {
+
+
+public class SimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
     static final String LOG_TAG = "GSM";
-    static final boolean DBG = false;
 
-    private GSMPhone phone;
-    private AdnRecordCache adnCache;
-    private final Object mLock = new Object();
-    private int recordSize[];
-    private boolean success;
-    private List<AdnRecord> records;
-
-    private static final boolean ALLOW_SIM_OP_IN_UI_THREAD = false;
-
-    private static final int EVENT_GET_SIZE_DONE = 1;
-    private static final int EVENT_LOAD_DONE = 2;
-    private static final int EVENT_UPDATE_DONE = 3;
 
     Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             AsyncResult ar;
 
-            switch (msg.what) {
-                case EVENT_GET_SIZE_DONE:
-                    ar = (AsyncResult) msg.obj;
-                    synchronized (mLock) {
-                        if (ar.exception == null) {
-                            recordSize = (int[])ar.result;
-                            // recordSize[0]  is the record length
-                            // recordSize[1]  is the total length of the EF file
-                            // recordSize[2]  is the number of records in the EF file
-                            log("GET_RECORD_SIZE Size " + recordSize[0] +
-                                    " total " + recordSize[1] +
-                                    " #record " + recordSize[2]);
-                            mLock.notifyAll();
-                        }
-                    }
-                    break;
-                case EVENT_UPDATE_DONE:
-                    ar = (AsyncResult) msg.obj;
-                    synchronized (mLock) {
-                        success = (ar.exception == null);
-                        mLock.notifyAll();
-                    }
-                    break;
-                case EVENT_LOAD_DONE:
-                    ar = (AsyncResult)msg.obj;
-                    synchronized (mLock) {
-                        if (ar.exception == null) {
-                            records = (List<AdnRecord>)
-                                    ((ArrayList<AdnRecord>) ar.result);
-                        } else {
-                            if(DBG) log("Cannot load ADN records");
-                            if (records != null) {
-                                records.clear();
-                            }
-                        }
-                        mLock.notifyAll();
-                    }
+            switch(msg.what) {
+                default:
+                    mBaseHandler.handleMessage(msg);
                     break;
             }
         }
     };
 
     public SimPhoneBookInterfaceManager(GSMPhone phone) {
-        this.phone = phone;
+        super(phone);
         adnCache = phone.mSIMRecords.getAdnCache();
-        publish();
+        //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
     }
 
-    private void publish() {
-        ServiceManager.addService("simphonebook", this);
+    public void dispose() {
+        super.dispose();
     }
 
-    /**
-     * Replace oldAdn with newAdn in ADN-like record in EF
-     *
-     * getAdnRecordsInEf must be called at least once before this function,
-     * otherwise an error will be returned
-     * throws SecurityException if no WRITE_CONTACTS permission
-     *
-     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
-     * @param oldTag adn tag to be replaced
-     * @param oldPhoneNumber adn number to be replaced
-     *        Set both oldTag and oldPhoneNubmer to "" means to replace an
-     *        empty record, aka, insert new record
-     * @param newTag adn tag to be stored
-     * @param newPhoneNumber adn number ot be stored
-     *        Set both newTag and newPhoneNubmer to "" means to replace the old
-     *        record with empty one, aka, delete old record
-     * @param pin2 required to update EF_FDN, otherwise must be null
-     * @return true for success
-     */
-    public boolean
-    updateAdnRecordsInEfBySearch (int efid,
-            String oldTag, String oldPhoneNumber,
-            String newTag, String newPhoneNumber, String pin2) {
-
-
-        if (phone.getContext().checkCallingOrSelfPermission(
-                android.Manifest.permission.WRITE_CONTACTS)
-            != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "Requires android.permission.WRITE_CONTACTS permission");
-        }
-
-        
-        if (DBG) log("updateAdnRecordsInEfBySearch: efid=" + efid +
-                " ("+ oldTag + "," + oldPhoneNumber + ")"+ "==>" +
-                " ("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
-        synchronized(mLock) {
-            checkThread();
-            success = false;
-            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
-            AdnRecord oldAdn = new AdnRecord(oldTag, oldPhoneNumber);
-            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
-            adnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                log("interrupted while trying to update by search");
-            }
-        }
-        return success;
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SimPhoneBookInterfaceManager finalized");
     }
 
-    /**
-     * Update an ADN-like EF record by record index
-     *
-     * This is useful for iteration the whole ADN file, such as write the whole
-     * phone book or erase/format the whole phonebook
-     * throws SecurityException if no WRITE_CONTACTS permission
-     *
-     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
-     * @param newTag adn tag to be stored
-     * @param newPhoneNumber adn number to be stored
-     *        Set both newTag and newPhoneNubmer to "" means to replace the old
-     *        record with empty one, aka, delete old record
-     * @param index is 1-based adn record index to be updated
-     * @param pin2 required to update EF_FDN, otherwise must be null
-     * @return true for success
-     */
-    public boolean
-    updateAdnRecordsInEfByIndex(int efid, String newTag,
-            String newPhoneNumber, int index, String pin2) {
-
-        if (phone.getContext().checkCallingOrSelfPermission(
-                android.Manifest.permission.WRITE_CONTACTS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "Requires android.permission.WRITE_CONTACTS permission");
-        }
-
-        if (DBG) log("updateAdnRecordsInEfByIndex: efid=" + efid +
-                " Index=" + index + " ==> " +
-                "("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
-        synchronized(mLock) {
-            checkThread();
-            success = false;
-            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
-            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
-            adnCache.updateAdnByIndex(efid, newAdn, index, pin2, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                log("interrupted while trying to update by index");
-            }
-        }
-        return success;
-    }
-
-    /**
-     * Get the capacity of records in efid
-     *
-     * @param efid the EF id of a ADN-like SIM
-     * @return  int[3] array
-     *            recordSizes[0]  is the single record length
-     *            recordSizes[1]  is the total length of the EF file
-     *            recordSizes[2]  is the number of records in the EF file
-     */
     public int[] getAdnRecordsSize(int efid) {
-        if (DBG) log("getAdnRecordsSize: efid=" + efid);
+        if (DBG) logd("getAdnRecordsSize: efid=" + efid);
         synchronized(mLock) {
             checkThread();
             recordSize = new int[3];
-            Message response = mHandler.obtainMessage(EVENT_GET_SIZE_DONE);
-            phone.mSIMFileHandler.getEFLinearRecordSize(efid, response);
+
+            //Using mBaseHandler, no difference in EVENT_GET_SIZE_DONE handling
+            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE);
+
+            phone.getIccFileHandler().getEFLinearRecordSize(efid, response);
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to load from the SIM");
+                logd("interrupted while trying to load from the SIM");
             }
         }
 
         return recordSize;
     }
 
-    /**
-     * Loads the AdnRecords in efid and returns them as a
-     * List of AdnRecords
-     *
-     * throws SecurityException if no READ_CONTACTS permission
-     *
-     * @param efid the EF id of a ADN-like SIM
-     * @return List of AdnRecord
-     */
-    public List<AdnRecord> getAdnRecordsInEf(int efid) {
-
-        if (phone.getContext().checkCallingOrSelfPermission(
-                android.Manifest.permission.READ_CONTACTS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "Requires android.permission.READ_CONTACTS permission");
-        }
-
-        if (DBG) log("getAdnRecordsInEF: efid=" + efid);
-
-        synchronized(mLock) {
-            checkThread();
-            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
-            adnCache.requestLoadAllAdnLike(efid, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                log("interrupted while trying to load from the SIM");
-            }
-        }
-            return records;
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[SimPbInterfaceManager] " + msg);
     }
 
-    private void checkThread() {
-        if (!ALLOW_SIM_OP_IN_UI_THREAD) {
-            // Make sure this isn't the UI thread, since it will block
-            if (mHandler.getLooper().equals(Looper.myLooper())) {
-                Log.e(LOG_TAG, "query() called on the main UI thread!");
-                throw new IllegalStateException("You cannot call query on this provder from the main UI thread.");
-            }
-        }
-    }
-
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[SpbInterfaceManager] " + msg);
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[SimPbInterfaceManager] " + msg);
     }
 }
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
index c3df0d0..875d8d0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
@@ -16,27 +16,31 @@
 
 package com.android.internal.telephony.gsm;
 
-import android.app.PendingIntent;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
-import android.os.ServiceManager;
-import android.telephony.gsm.SmsManager;
 import android.util.Log;
 
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.SmsRawData;
+
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
+
 /**
  * SimSmsInterfaceManager to provide an inter-process communication to
  * access Sms in Sim.
  */
-public class SimSmsInterfaceManager extends ISms.Stub {
+public class SimSmsInterfaceManager extends IccSmsInterfaceManager {
     static final String LOG_TAG = "GSM";
-    static final boolean DBG = false;
+    static final boolean DBG = true;
 
-    private GSMPhone mPhone;
     private final Object mLock = new Object();
     private boolean mSuccess;
     private List<SmsRawData> mSms;
@@ -76,33 +80,31 @@
     };
 
     public SimSmsInterfaceManager(GSMPhone phone) {
-        this.mPhone = phone;
-        ServiceManager.addService("isms", this);
+        super(phone);
+        mDispatcher = new GsmSMSDispatcher(phone);
     }
 
-    private void enforceReceiveAndSend(String message) {
-        Context context = mPhone.getContext();
+    public void dispose() {
+    }
 
-        context.enforceCallingPermission(
-                "android.permission.RECEIVE_SMS", message);
-        context.enforceCallingPermission(
-                "android.permission.SEND_SMS", message);
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SimSmsInterfaceManager finalized");
     }
 
     /**
      * Update the specified message on the SIM.
      *
      * @param index record index of message to update
-     * @param status new message status (STATUS_ON_SIM_READ,
-     *                  STATUS_ON_SIM_UNREAD, STATUS_ON_SIM_SENT,
-     *                  STATUS_ON_SIM_UNSENT, STATUS_ON_SIM_FREE)
+     * @param status new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
      * @param pdu the raw PDU to store
      * @return success or not
      *
      */
     public boolean
-    updateMessageOnSimEf(int index, int status, byte[] pdu) {
-        if (DBG) log("updateMessageOnSimEf: index=" + index +
+    updateMessageOnIccEf(int index, int status, byte[] pdu) {
+        if (DBG) log("updateMessageOnIccEf: index=" + index +
                 " status=" + status + " ==> " +
                 "("+ pdu + ")");
         enforceReceiveAndSend("Updating message on SIM");
@@ -110,13 +112,14 @@
             mSuccess = false;
             Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
 
-            if (status == SmsManager.STATUS_ON_SIM_FREE) {
+            if (status == STATUS_ON_ICC_FREE) {
                 // Special case FREE: call deleteSmsOnSim instead of
                 // manipulating the SIM record
                 mPhone.mCM.deleteSmsOnSim(index, response);
             } else {
                 byte[] record = makeSmsRecordData(status, pdu);
-                mPhone.mSIMFileHandler.updateEFLinearFixed( SimConstants.EF_SMS,
+                ((SIMFileHandler)mPhone.getIccFileHandler()).updateEFLinearFixed(
+                        IccConstants.EF_SMS,
                         index, record, null, response);
             }
             try {
@@ -132,21 +135,21 @@
      * Copy a raw SMS PDU to the SIM.
      *
      * @param pdu the raw PDU to store
-     * @param status message status (STATUS_ON_SIM_READ, STATUS_ON_SIM_UNREAD,
-     *               STATUS_ON_SIM_SENT, STATUS_ON_SIM_UNSENT)
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
      * @return success or not
      *
      */
-    public boolean copyMessageToSimEf(int status, byte[] pdu, byte[] smsc) {
-        if (DBG) log("copyMessageToSimEf: status=" + status + " ==> " +
+    public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
+        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
                 "pdu=("+ pdu + "), smsm=(" + smsc +")");
         enforceReceiveAndSend("Copying message to SIM");
         synchronized(mLock) {
             mSuccess = false;
             Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
 
-            mPhone.mCM.writeSmsToSim(status, SimUtils.bytesToHexString(smsc),
-                    SimUtils.bytesToHexString(pdu), response);
+            mPhone.mCM.writeSmsToSim(status, IccUtils.bytesToHexString(smsc),
+                    IccUtils.bytesToHexString(pdu), response);
 
             try {
                 mLock.wait();
@@ -158,11 +161,11 @@
     }
 
     /**
-     * Retrieves all messages currently stored on SIM.
+     * Retrieves all messages currently stored on ICC.
      *
-     * @return list of SmsRawData of all sms on SIM
+     * @return list of SmsRawData of all sms on ICC
      */
-    public List<SmsRawData> getAllMessagesFromSimEf() {
+    public List<SmsRawData> getAllMessagesFromIccEf() {
         if (DBG) log("getAllMessagesFromEF");
 
         Context context = mPhone.getContext();
@@ -172,7 +175,7 @@
                 "Reading messages from SIM");
         synchronized(mLock) {
             Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
-            mPhone.mSIMFileHandler.loadEFLinearFixedAll(SimConstants.EF_SMS,
+            ((SIMFileHandler)mPhone.getIccFileHandler()).loadEFLinearFixedAll(IccConstants.EF_SMS,
                     response);
 
             try {
@@ -184,119 +187,7 @@
         return mSms;
     }
 
-    /**
-     * Send a Raw PDU SMS
-     *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  defatult SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
-     *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is delivered to the recipient.  The
-     *  raw pdu of the status report is in the extended data ("pdu").
-     */
-    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        Context context = mPhone.getContext();
-
-        context.enforceCallingPermission(
-                "android.permission.SEND_SMS",
-                "Sending SMS message");
-        if (DBG) log("sendRawPdu: smsc=" + smsc +
-                " pdu="+ pdu + " sentIntent" + sentIntent +
-                " deliveryIntent" + deliveryIntent);
-        mPhone.mSMS.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
-    }
-
-    /**
-     * Send a multi-part text based SMS.
-     * 
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
-     *   the current default SMSC
-     * @param parts an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of 
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been sent.
-     *   The result code will be <code>Activity.RESULT_OK<code> for success,
-     *   or one of these errors:
-     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *   <code>RESULT_ERROR_RADIO_OFF</code>
-     *   <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of 
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been delivered
-     *   to the recipient.  The raw pdu of the status report is in the
-     *   extended data ("pdu").
-     */
-    public void sendMultipartText(String destinationAddress, String scAddress, List<String> parts,
-            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
-        Context context = mPhone.getContext();
-
-        context.enforceCallingPermission(
-                "android.permission.SEND_SMS",
-                "Sending SMS message");
-        if (DBG) log("sendMultipartText");
-        mPhone.mSMS.sendMultipartText(destinationAddress, scAddress, (ArrayList<String>) parts,
-                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
-    }
-
-    /**
-     * Generates an EF_SMS record from status and raw PDU.
-     *
-     * @param status Message status.  See TS 51.011 10.5.3.
-     * @param pdu Raw message PDU.
-     * @return byte array for the record.
-     */
-    private byte[] makeSmsRecordData(int status, byte[] pdu) {
-        byte[] data = new byte[SimConstants.SMS_RECORD_LENGTH];
-
-        // Status bits for this record.  See TS 51.011 10.5.3
-        data[0] = (byte)(status & 7);
-
-        System.arraycopy(pdu, 0, data, 1, pdu.length);
-
-        // Pad out with 0xFF's.
-        for (int j = pdu.length+1; j < SimConstants.SMS_RECORD_LENGTH; j++) {
-            data[j] = -1;
-        }
-
-        return data;
-    }
-
-    /**
-     * create SmsRawData lists from all sms record byte[]
-     * Use null to indicate "free" record
-     *
-     * @param messages List of message records from EF_SMS.
-     * @return SmsRawData list of all in-used records
-     */
-    private ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) {
-        int count = messages.size();
-        ArrayList<SmsRawData> ret;
-
-        ret = new ArrayList<SmsRawData>(count);
-
-        for (int i = 0; i < count; i++) {
-            byte[] ba = messages.get(i);
-            if (ba[0] == 0) {
-                ret.add(null);
-            } else {
-                ret.add(new SmsRawData(messages.get(i)));
-            }
-        }
-
-        return ret;
-    }
-
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[SmsInterfaceManager] " + msg);
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[SimSmsInterfaceManager] " + msg);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
index 00879ce..30543c7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
@@ -34,9 +34,8 @@
     int curDataOffset;
     int curDataLength;
     boolean hasValidTlvObject;
-    
-    public SimTlv(byte[] record, int offset, int length)
-    {
+
+    public SimTlv(byte[] record, int offset, int length) {
         this.record = record;
 
         this.tlvOffset = offset;
@@ -46,19 +45,15 @@
         hasValidTlvObject = parseCurrentTlvObject();
     }
 
-    public boolean
-    nextObject()
-    {
+    public boolean nextObject() {
         if (!hasValidTlvObject) return false;
 
         curOffset = curDataOffset + curDataLength;
-        hasValidTlvObject = parseCurrentTlvObject(); 
+        hasValidTlvObject = parseCurrentTlvObject();
         return hasValidTlvObject;
     }
 
-    public boolean
-    isValidObject()
-    {
+    public boolean isValidObject() {
         return hasValidTlvObject;
     }
 
@@ -68,9 +63,7 @@
      * 0 and 0xff are invalid tag values
      * valid tags range from 1 - 0xfe
      */
-    public int
-    getTag()
-    {
+    public int getTag() {
         if (!hasValidTlvObject) return 0;
         return record[curOffset] & 0xff;
     }
@@ -79,10 +72,8 @@
      * Returns data associated with current TLV object
      * returns null if !isValidObject()
      */
-    
-    public byte[]
-    getData()
-    {
+
+    public byte[] getData() {
         if (!hasValidTlvObject) return null;
 
         byte[] ret = new byte[curDataLength];
@@ -95,14 +86,12 @@
      * @return false on invalid record, true on valid record
      */
 
-    private boolean
-    parseCurrentTlvObject()
-    {   
+    private boolean parseCurrentTlvObject() {
         // 0x00 and 0xff are invalid tag values
         if (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
             return false;
         }
-        
+
         try {
             if ((record[curOffset + 1] & 0xff) < 0x80) {
                 // one byte length 0 - 0x7f
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
new file mode 100644
index 0000000..867b719
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -0,0 +1,1058 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.gsm;
+
+import android.os.Parcel;
+import android.telephony.PhoneNumberUtils;
+import android.text.format.Time;
+import android.util.Config;
+import android.util.Log;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+
+import static android.telephony.SmsMessage.ENCODING_7BIT;
+import static android.telephony.SmsMessage.ENCODING_8BIT;
+import static android.telephony.SmsMessage.ENCODING_16BIT;
+import static android.telephony.SmsMessage.ENCODING_UNKNOWN;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+import static android.telephony.SmsMessage.MessageClass;
+
+/**
+ * A Short Message Service message.
+ *
+ */
+public class SmsMessage extends SmsMessageBase{
+    static final String LOG_TAG = "GSM";
+
+    private MessageClass messageClass;
+
+    /**
+     * TP-Message-Type-Indicator
+     * 9.2.3
+     */
+    private int mti;
+
+    /** TP-Protocol-Identifier (TP-PID) */
+    private int protocolIdentifier;
+
+    // TP-Data-Coding-Scheme
+    // see TS 23.038
+    private int dataCodingScheme;
+
+    // TP-Reply-Path
+    // e.g. 23.040 9.2.2.1
+    private boolean replyPathPresent = false;
+
+    // "Message Marked for Automatic Deletion Group"
+    // 23.038 Section 4
+    private boolean automaticDeletion;
+
+    /** True if Status Report is for SMS-SUBMIT; false for SMS-COMMAND. */
+    private boolean forSubmit;
+
+    /** The address of the receiver. */
+    private GsmSmsAddress recipientAddress;
+
+    /** Time when SMS-SUBMIT was delivered from SC to MSE. */
+    private long dischargeTimeMillis;
+
+    /**
+     *  TP-Status - status of a previously submitted SMS.
+     *  This field applies to SMS-STATUS-REPORT messages.  0 indicates success;
+     *  see TS 23.040, 9.2.3.15 for description of other possible values.
+     */
+    private int status;
+
+    /**
+     *  TP-Status - status of a previously submitted SMS.
+     *  This field is true iff the message is a SMS-STATUS-REPORT message.
+     */
+    private boolean isStatusReportMessage = false;
+
+    public static class SubmitPdu extends SubmitPduBase {
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the
+     * +CMT unsolicited response (PDU mode, of course)
+     *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
+     *
+     * Only public for debugging
+     *
+     * {@hide}
+     */
+    public static SmsMessage newFromCMT(String[] lines) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(IccUtils.hexStringToBytes(lines[1]));
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /** @hide */
+    public static SmsMessage newFromCMTI(String line) {
+        // the thinking here is not to read the message immediately
+        // FTA test case
+        Log.e(LOG_TAG, "newFromCMTI: not yet supported");
+        return null;
+    }
+
+    /** @hide */
+    public static SmsMessage newFromCDS(String line) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(IccUtils.hexStringToBytes(line));
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "CDS SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Note: This functionality is currently not supported in GSM mode.
+     * @hide
+     */
+    public static SmsMessageBase newFromParcel(Parcel p){
+        Log.w(LOG_TAG, "newFromParcel: is not supported in GSM mode.");
+        return null;
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by SmsManager.getAllMessagesFromSim + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        try {
+            SmsMessage msg = new SmsMessage();
+
+            msg.indexOnIcc = index;
+
+            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
+            // or STORED_UNSENT
+            // See TS 51.011 10.5.3
+            if ((data[0] & 1) == 0) {
+                Log.w(LOG_TAG,
+                        "SMS parsing failed: Trying to parse a free record");
+                return null;
+            } else {
+                msg.statusOnIcc = data[0] & 0x07;
+            }
+
+            int size = data.length - 1;
+
+            // Note: Data may include trailing FF's.  That's OK; message
+            // should still parse correctly.
+            byte[] pdu = new byte[size];
+            System.arraycopy(data, 1, pdu, 0, size);
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
+     * length in bytes (not hex chars) less the SMSC header
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        int len = pdu.length() / 2;
+        int smscLen = 0;
+
+        smscLen = Integer.parseInt(pdu.substring(0, 2), 16);
+
+        return len - smscLen - 1;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] header) {
+
+        // Perform null parameter checks.
+        if (message == null || destinationAddress == null) {
+            return null;
+        }
+
+        SubmitPdu ret = new SubmitPdu();
+        // MTI = SMS-SUBMIT, UDHI = header != null
+        byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00));
+        ByteArrayOutputStream bo = getSubmitPduHead(
+                scAddress, destinationAddress, mtiByte,
+                statusReportRequested, ret);
+
+        try {
+            // First, try encoding it with the GSM alphabet
+
+            // User Data (and length)
+            byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header);
+
+            if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) {
+                // Message too long
+                return null;
+            }
+
+            // TP-Data-Coding-Scheme
+            // Default encoding, uncompressed
+            bo.write(0x00);
+
+            // (no TP-Validity-Period)
+
+            bo.write(userData, 0, userData.length);
+        } catch (EncodeException ex) {
+            byte[] userData, textPart;
+            // Encoding to the 7-bit alphabet failed. Let's see if we can
+            // send it as a UCS-2 encoded message
+
+            try {
+                textPart = message.getBytes("utf-16be");
+            } catch (UnsupportedEncodingException uex) {
+                Log.e(LOG_TAG,
+                      "Implausible UnsupportedEncodingException ",
+                      uex);
+                return null;
+            }
+
+            if (header != null) {
+                userData = new byte[header.length + textPart.length];
+
+                System.arraycopy(header, 0, userData, 0, header.length);
+                System.arraycopy(textPart, 0, userData, header.length, textPart.length);
+            }
+            else {
+                userData = textPart;
+            }
+
+            if (userData.length > MAX_USER_DATA_BYTES) {
+                // Message too long
+                return null;
+            }
+
+            // TP-Data-Coding-Scheme
+            // Class 3, UCS-2 encoding, uncompressed
+            bo.write(0x0b);
+
+            // (no TP-Validity-Period)
+
+            // TP-UDL
+            bo.write(userData.length);
+
+            bo.write(userData, 0, userData.length);
+        }
+
+        ret.encodedMessage = bo.toByteArray();
+        return ret;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested) {
+
+        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the dat for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, short destinationPort, byte[] data,
+            boolean statusReportRequested) {
+        if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) {
+            Log.e(LOG_TAG, "SMS data message may only contain "
+                    + (MAX_USER_DATA_BYTES - 7) + " bytes");
+            return null;
+        }
+
+        SubmitPdu ret = new SubmitPdu();
+        ByteArrayOutputStream bo = getSubmitPduHead(
+                scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT,
+                                                            // TP-UDHI = true
+                statusReportRequested, ret);
+
+        // TP-Data-Coding-Scheme
+        // No class, 8 bit data
+        bo.write(0x04);
+
+        // (no TP-Validity-Period)
+
+        // User data size
+        bo.write(data.length + 7);
+
+        // User data header size
+        bo.write(0x06); // header is 6 octets
+
+        // User data header, indicating the destination port
+        bo.write(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT); // port
+                                                                // addressing
+                                                                // header
+        bo.write(0x04); // each port is 2 octets
+        bo.write((destinationPort >> 8) & 0xFF); // MSB of destination port
+        bo.write(destinationPort & 0xFF); // LSB of destination port
+        bo.write(0x00); // MSB of originating port
+        bo.write(0x00); // LSB of originating port
+
+        // User data
+        bo.write(data, 0, data.length);
+
+        ret.encodedMessage = bo.toByteArray();
+        return ret;
+    }
+
+    /**
+     * Create the beginning of a SUBMIT PDU.  This is the part of the
+     * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu},
+     * one of which takes a byte array and the other of which takes a
+     * <code>String</code>.
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param mtiByte
+     * @param ret <code>SubmitPdu</code> containing the encoded SC
+     *        address, if applicable, and the encoded message
+     */
+    private static ByteArrayOutputStream getSubmitPduHead(
+            String scAddress, String destinationAddress, byte mtiByte,
+            boolean statusReportRequested, SubmitPdu ret) {
+        ByteArrayOutputStream bo = new ByteArrayOutputStream(
+                MAX_USER_DATA_BYTES + 40);
+
+        // SMSC address with length octet, or 0
+        if (scAddress == null) {
+            ret.encodedScAddress = null;
+        } else {
+            ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(
+                    scAddress);
+        }
+
+        // TP-Message-Type-Indicator (and friends)
+        if (statusReportRequested) {
+            // Set TP-Status-Report-Request bit.
+            mtiByte |= 0x20;
+            if (Config.LOGD) Log.d(LOG_TAG, "SMS status report requested");
+        }
+        bo.write(mtiByte);
+
+        // space for TP-Message-Reference
+        bo.write(0);
+
+        byte[] daBytes;
+
+        daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress);
+
+        // destination address length in BCD digits, ignoring TON byte and pad
+        // TODO Should be better.
+        bo.write((daBytes.length - 1) * 2
+                - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0));
+
+        // destination address
+        bo.write(daBytes, 0, daBytes.length);
+
+        // TP-Protocol-Identifier
+        bo.write(0);
+        return bo;
+    }
+
+    static class PduParser {
+        byte pdu[];
+        int cur;
+        SmsHeader userDataHeader;
+        byte[] userData;
+        int mUserDataSeptetPadding;
+        int mUserDataSize;
+
+        PduParser(String s) {
+            this(IccUtils.hexStringToBytes(s));
+        }
+
+        PduParser(byte[] pdu) {
+            this.pdu = pdu;
+            cur = 0;
+            mUserDataSeptetPadding = 0;
+        }
+
+        /**
+         * Parse and return the SC address prepended to SMS messages coming via
+         * the TS 27.005 / AT interface.  Returns null on invalid address
+         */
+        String getSCAddress() {
+            int len;
+            String ret;
+
+            // length of SC Address
+            len = getByte();
+
+            if (len == 0) {
+                // no SC address
+                ret = null;
+            } else {
+                // SC address
+                try {
+                    ret = PhoneNumberUtils
+                            .calledPartyBCDToString(pdu, cur, len);
+                } catch (RuntimeException tr) {
+                    Log.d(LOG_TAG, "invalid SC address: ", tr);
+                    ret = null;
+                }
+            }
+
+            cur += len;
+
+            return ret;
+        }
+
+        /**
+         * returns non-sign-extended byte value
+         */
+        int getByte() {
+            return pdu[cur++] & 0xff;
+        }
+
+        /**
+         * Any address except the SC address (eg, originating address) See TS
+         * 23.040 9.1.2.5
+         */
+        GsmSmsAddress getAddress() {
+            GsmSmsAddress ret;
+
+            // "The Address-Length field is an integer representation of
+            // the number field, i.e. excludes any semi octet containing only
+            // fill bits."
+            // The TOA field is not included as part of this
+            int addressLength = pdu[cur] & 0xff;
+            int lengthBytes = 2 + (addressLength + 1) / 2;
+
+            ret = new GsmSmsAddress(pdu, cur, lengthBytes);
+
+            cur += lengthBytes;
+
+            return ret;
+        }
+
+        /**
+         * Parses an SC timestamp and returns a currentTimeMillis()-style
+         * timestamp
+         */
+
+        long getSCTimestampMillis() {
+            // TP-Service-Centre-Time-Stamp
+            int year = IccUtils.bcdByteToInt(pdu[cur++]);
+            int month = IccUtils.bcdByteToInt(pdu[cur++]);
+            int day = IccUtils.bcdByteToInt(pdu[cur++]);
+            int hour = IccUtils.bcdByteToInt(pdu[cur++]);
+            int minute = IccUtils.bcdByteToInt(pdu[cur++]);
+            int second = IccUtils.bcdByteToInt(pdu[cur++]);
+
+            // For the timezone, the most significant bit of the
+            // least signficant nibble is the sign byte
+            // (meaning the max range of this field is 79 quarter-hours,
+            // which is more than enough)
+
+            byte tzByte = pdu[cur++];
+
+            // Mask out sign bit.
+            int timezoneOffset = IccUtils
+                    .bcdByteToInt((byte) (tzByte & (~0x08)));
+
+            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset
+                    : -timezoneOffset;
+
+            Time time = new Time(Time.TIMEZONE_UTC);
+
+            // It's 2006.  Should I really support years < 2000?
+            time.year = year >= 90 ? year + 1900 : year + 2000;
+            time.month = month - 1;
+            time.monthDay = day;
+            time.hour = hour;
+            time.minute = minute;
+            time.second = second;
+
+            // Timezone offset is in quarter hours.
+            return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000);
+        }
+
+        /**
+         * Pulls the user data out of the PDU, and separates the payload from
+         * the header if there is one.
+         *
+         * @param hasUserDataHeader true if there is a user data header
+         * @param dataInSeptets true if the data payload is in septets instead
+         *  of octets
+         * @return the number of septets or octets in the user data payload
+         */
+        int constructUserData(boolean hasUserDataHeader, boolean dataInSeptets) {
+            int offset = cur;
+            int userDataLength = pdu[offset++] & 0xff;
+            int headerSeptets = 0;
+
+            if (hasUserDataHeader) {
+                int userDataHeaderLength = pdu[offset++] & 0xff;
+
+                byte[] udh = new byte[userDataHeaderLength];
+                System.arraycopy(pdu, offset, udh, 0, userDataHeaderLength);
+                userDataHeader = SmsHeader.parse(udh);
+                offset += userDataHeaderLength;
+
+                int headerBits = (userDataHeaderLength + 1) * 8;
+                headerSeptets = headerBits / 7;
+                headerSeptets += (headerBits % 7) > 0 ? 1 : 0;
+                mUserDataSeptetPadding = (headerSeptets * 7) - headerBits;
+            }
+
+            /*
+             * Here we just create the user data length to be the remainder of
+             * the pdu minus the user data hearder. This is because the count
+             * could mean the number of uncompressed sepets if the userdata is
+             * encoded in 7-bit.
+             */
+            userData = new byte[pdu.length - offset];
+            System.arraycopy(pdu, offset, userData, 0, userData.length);
+            cur = offset;
+
+            if (dataInSeptets) {
+                // Return the number of septets
+                return userDataLength - headerSeptets;
+            } else {
+                // Return the number of octets
+                return userData.length;
+            }
+        }
+
+        /**
+         * Returns the user data payload, not including the headers
+         *
+         * @return the user data payload, not including the headers
+         */
+        byte[] getUserData() {
+            return userData;
+        }
+
+        /**
+         * Returns the number of padding bits at the begining of the user data
+         * array before the start of the septets.
+         *
+         * @return the number of padding bits at the begining of the user data
+         * array before the start of the septets
+         */
+        int getUserDataSeptetPadding() {
+            return mUserDataSeptetPadding;
+        }
+
+        /**
+         * Returns an object representing the user data headers
+         *
+         * @return an object representing the user data headers
+         *
+         * {@hide}
+         */
+        SmsHeader getUserDataHeader() {
+            return userDataHeader;
+        }
+
+/*
+        XXX Not sure what this one is supposed to be doing, and no one is using
+        it.
+        String getUserDataGSM8bit() {
+            // System.out.println("remainder of pud:" +
+            // HexDump.dumpHexString(pdu, cur, pdu.length - cur));
+            int count = pdu[cur++] & 0xff;
+            int size = pdu[cur++];
+
+            // skip over header for now
+            cur += size;
+
+            if (pdu[cur - 1] == 0x01) {
+                int tid = pdu[cur++] & 0xff;
+                int type = pdu[cur++] & 0xff;
+
+                size = pdu[cur++] & 0xff;
+
+                int i = cur;
+
+                while (pdu[i++] != '\0') {
+                }
+
+                int length = i - cur;
+                String mimeType = new String(pdu, cur, length);
+
+                cur += length;
+
+                if (false) {
+                    System.out.println("tid = 0x" + HexDump.toHexString(tid));
+                    System.out.println("type = 0x" + HexDump.toHexString(type));
+                    System.out.println("header size = " + size);
+                    System.out.println("mimeType = " + mimeType);
+                    System.out.println("remainder of header:" +
+                     HexDump.dumpHexString(pdu, cur, (size - mimeType.length())));
+                }
+
+                cur += size - mimeType.length();
+
+                // System.out.println("data count = " + count + " cur = " + cur
+                // + " :" + HexDump.dumpHexString(pdu, cur, pdu.length - cur));
+
+                MMSMessage msg = MMSMessage.parseEncoding(mContext, pdu, cur,
+                        pdu.length - cur);
+            } else {
+                System.out.println(new String(pdu, cur, pdu.length - cur - 1));
+            }
+
+            return IccUtils.bytesToHexString(pdu);
+        }
+*/
+
+        /**
+         * Interprets the user data payload as pack GSM 7bit characters, and
+         * decodes them into a String.
+         *
+         * @param septetCount the number of septets in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataGSM7Bit(int septetCount) {
+            String ret;
+
+            ret = GsmAlphabet.gsm7BitPackedToString(pdu, cur, septetCount,
+                    mUserDataSeptetPadding);
+
+            cur += (septetCount * 7) / 8;
+
+            return ret;
+        }
+
+        /**
+         * Interprets the user data payload as UCS2 characters, and
+         * decodes them into a String.
+         *
+         * @param byteCount the number of bytes in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataUCS2(int byteCount) {
+            String ret;
+
+            try {
+                ret = new String(pdu, cur, byteCount, "utf-16");
+            } catch (UnsupportedEncodingException ex) {
+                ret = "";
+                Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex);
+            }
+
+            cur += byteCount;
+            return ret;
+        }
+
+        boolean moreDataPresent() {
+            return (pdu.length > cur);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public int getProtocolIdentifier() {
+        return protocolIdentifier;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isReplace() {
+        return (protocolIdentifier & 0xc0) == 0x40
+                && (protocolIdentifier & 0x3f) > 0
+                && (protocolIdentifier & 0x3f) < 8;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isCphsMwiMessage() {
+        return ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear()
+                || ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isMWIClearMessage() {
+        if (isMwi && (mwiSense == false)) {
+            return true;
+        }
+
+        return originatingAddress != null
+                && ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isMWISetMessage() {
+        if (isMwi && (mwiSense == true)) {
+            return true;
+        }
+
+        return originatingAddress != null
+                && ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isMwiDontStore() {
+        if (isMwi && mwiDontStore) {
+            return true;
+        }
+
+        if (isCphsMwiMessage()) {
+            // See CPHS 4.2 Section B.4.2.1
+            // If the user data is a single space char, do not store
+            // the message. Otherwise, store and display as usual
+            if (" ".equals(getMessageBody())) {
+                ;
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    public int getStatus() {
+        return status;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isStatusReportMessage() {
+        return isStatusReportMessage;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isReplyPathPresent() {
+        return replyPathPresent;
+    }
+
+    /**
+     * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6]
+     * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format:
+     * ME/TA converts each octet of TP data unit into two IRA character long
+     * hexad number (e.g. octet with integer value 42 is presented to TE as two
+     * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast,
+     * something else...
+     */
+    private void parsePdu(byte[] pdu) {
+        mPdu = pdu;
+        // Log.d(LOG_TAG, "raw sms mesage:");
+        // Log.d(LOG_TAG, s);
+
+        PduParser p = new PduParser(pdu);
+
+        scAddress = p.getSCAddress();
+
+        if (scAddress != null) {
+            if (Config.LOGD) Log.d(LOG_TAG, "SMS SC address: " + scAddress);
+        }
+
+        // TODO(mkf) support reply path, user data header indicator
+
+        // TP-Message-Type-Indicator
+        // 9.2.3
+        int firstByte = p.getByte();
+
+        mti = firstByte & 0x3;
+        switch (mti) {
+        // TP-Message-Type-Indicator
+        // 9.2.3
+        case 0:
+            parseSmsDeliver(p, firstByte);
+            break;
+        case 2:
+            parseSmsStatusReport(p, firstByte);
+            break;
+        default:
+            // TODO(mkf) the rest of these
+            throw new RuntimeException("Unsupported message type");
+        }
+    }
+
+    /**
+     * Parses a SMS-STATUS-REPORT message.
+     *
+     * @param p A PduParser, cued past the first byte.
+     * @param firstByte The first byte of the PDU, which contains MTI, etc.
+     */
+    private void parseSmsStatusReport(PduParser p, int firstByte) {
+        isStatusReportMessage = true;
+
+        // TP-Status-Report-Qualifier bit == 0 for SUBMIT
+        forSubmit = (firstByte & 0x20) == 0x00;
+        // TP-Message-Reference
+        messageRef = p.getByte();
+        // TP-Recipient-Address
+        recipientAddress = p.getAddress();
+        // TP-Service-Centre-Time-Stamp
+        scTimeMillis = p.getSCTimestampMillis();
+        // TP-Discharge-Time
+        dischargeTimeMillis = p.getSCTimestampMillis();
+        // TP-Status
+        status = p.getByte();
+
+        // The following are optional fields that may or may not be present.
+        if (p.moreDataPresent()) {
+            // TP-Parameter-Indicator
+            int extraParams = p.getByte();
+            int moreExtraParams = extraParams;
+            while ((moreExtraParams & 0x80) != 0) {
+                // We only know how to parse a few extra parameters, all
+                // indicated in the first TP-PI octet, so skip over any
+                // additional TP-PI octets.
+                moreExtraParams = p.getByte();
+            }
+            // TP-Protocol-Identifier
+            if ((extraParams & 0x01) != 0) {
+                protocolIdentifier = p.getByte();
+            }
+            // TP-Data-Coding-Scheme
+            if ((extraParams & 0x02) != 0) {
+                dataCodingScheme = p.getByte();
+            }
+            // TP-User-Data-Length (implies existence of TP-User-Data)
+            if ((extraParams & 0x04) != 0) {
+                boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
+                parseUserData(p, hasUserDataHeader);
+            }
+        }
+    }
+
+    private void parseSmsDeliver(PduParser p, int firstByte) {
+        replyPathPresent = (firstByte & 0x80) == 0x80;
+
+        originatingAddress = p.getAddress();
+
+        if (originatingAddress != null) {
+            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
+                    + originatingAddress.address);
+        }
+
+        // TP-Protocol-Identifier (TP-PID)
+        // TS 23.040 9.2.3.9
+        protocolIdentifier = p.getByte();
+
+        // TP-Data-Coding-Scheme
+        // see TS 23.038
+        dataCodingScheme = p.getByte();
+
+        if (Config.LOGV) {
+            Log.v(LOG_TAG, "SMS TP-PID:" + protocolIdentifier
+                    + " data coding scheme: " + dataCodingScheme);
+        }
+
+        scTimeMillis = p.getSCTimestampMillis();
+
+        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
+
+        boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
+
+        parseUserData(p, hasUserDataHeader);
+    }
+
+    /**
+     * Parses the User Data of an SMS.
+     *
+     * @param p The current PduParser.
+     * @param hasUserDataHeader Indicates whether a header is present in the
+     *                          User Data.
+     */
+    private void parseUserData(PduParser p, boolean hasUserDataHeader) {
+        boolean hasMessageClass = false;
+        boolean userDataCompressed = false;
+
+        int encodingType = ENCODING_UNKNOWN;
+
+        // Look up the data encoding scheme
+        if ((dataCodingScheme & 0x80) == 0) {
+            // Bits 7..4 == 0xxx
+            automaticDeletion = (0 != (dataCodingScheme & 0x40));
+            userDataCompressed = (0 != (dataCodingScheme & 0x20));
+            hasMessageClass = (0 != (dataCodingScheme & 0x10));
+
+            if (userDataCompressed) {
+                Log.w(LOG_TAG, "4 - Unsupported SMS data coding scheme "
+                        + "(compression) " + (dataCodingScheme & 0xff));
+            } else {
+                switch ((dataCodingScheme >> 2) & 0x3) {
+                case 0: // GSM 7 bit default alphabet
+                    encodingType = ENCODING_7BIT;
+                    break;
+
+                case 2: // UCS 2 (16bit)
+                    encodingType = ENCODING_16BIT;
+                    break;
+
+                case 1: // 8 bit data
+                case 3: // reserved
+                    Log.w(LOG_TAG, "1 - Unsupported SMS data coding scheme "
+                            + (dataCodingScheme & 0xff));
+                    encodingType = ENCODING_8BIT;
+                    break;
+                }
+            }
+        } else if ((dataCodingScheme & 0xf0) == 0xf0) {
+            automaticDeletion = false;
+            hasMessageClass = true;
+            userDataCompressed = false;
+
+            if (0 == (dataCodingScheme & 0x04)) {
+                // GSM 7 bit default alphabet
+                encodingType = ENCODING_7BIT;
+            } else {
+                // 8 bit data
+                encodingType = ENCODING_8BIT;
+            }
+        } else if ((dataCodingScheme & 0xF0) == 0xC0
+                || (dataCodingScheme & 0xF0) == 0xD0
+                || (dataCodingScheme & 0xF0) == 0xE0) {
+            // 3GPP TS 23.038 V7.0.0 (2006-03) section 4
+
+            // 0xC0 == 7 bit, don't store
+            // 0xD0 == 7 bit, store
+            // 0xE0 == UCS-2, store
+
+            if ((dataCodingScheme & 0xF0) == 0xE0) {
+                encodingType = ENCODING_16BIT;
+            } else {
+                encodingType = ENCODING_7BIT;
+            }
+
+            userDataCompressed = false;
+            boolean active = ((dataCodingScheme & 0x08) == 0x08);
+
+            // bit 0x04 reserved
+
+            if ((dataCodingScheme & 0x03) == 0x00) {
+                isMwi = true;
+                mwiSense = active;
+                mwiDontStore = ((dataCodingScheme & 0xF0) == 0xC0);
+            } else {
+                isMwi = false;
+
+                Log.w(LOG_TAG, "MWI for fax, email, or other "
+                        + (dataCodingScheme & 0xff));
+            }
+        } else {
+            Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme "
+                    + (dataCodingScheme & 0xff));
+        }
+
+        // set both the user data and the user data header.
+        int count = p.constructUserData(hasUserDataHeader,
+                encodingType == ENCODING_7BIT);
+        this.userData = p.getUserData();
+        this.userDataHeader = p.getUserDataHeader();
+
+        switch (encodingType) {
+        case ENCODING_UNKNOWN:
+        case ENCODING_8BIT:
+            messageBody = null;
+            break;
+
+        case ENCODING_7BIT:
+            messageBody = p.getUserDataGSM7Bit(count);
+            break;
+
+        case ENCODING_16BIT:
+            messageBody = p.getUserDataUCS2(count);
+            break;
+        }
+
+        if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'");
+
+        if (messageBody != null) {
+            parseMessageBody();
+        }
+
+        if (!hasMessageClass) {
+            messageClass = MessageClass.UNKNOWN;
+        } else {
+            switch (dataCodingScheme & 0x3) {
+            case 0:
+                messageClass = MessageClass.CLASS_0;
+                break;
+            case 1:
+                messageClass = MessageClass.CLASS_1;
+                break;
+            case 2:
+                messageClass = MessageClass.CLASS_2;
+                break;
+            case 3:
+                messageClass = MessageClass.CLASS_3;
+                break;
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MessageClass getMessageClass() {
+        return messageClass;
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java b/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
index 26c2175b..19d3279 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
@@ -20,9 +20,9 @@
 
 /**
  * Class for representing BER-TLV objects.
- * 
+ *
  * @see "ETSI TS 102 223 Annex C" for more information.
- * 
+ *
  * {@hide}
  */
 class BerTlv {
@@ -41,16 +41,16 @@
 
     /**
      * Gets a list of ComprehensionTlv objects contained in this BER-TLV object.
-     * 
+     *
      * @return A list of COMPREHENSION-TLV object
      */
     public List<ComprehensionTlv> getComprehensionTlvs() {
         return mCompTlvs;
     }
-    
+
     /**
      * Gets a tag id of the BER-TLV object.
-     * 
+     *
      * @return A tag integer.
      */
     public int getTag() {
@@ -59,7 +59,7 @@
 
     /**
      * Decodes a BER-TLV object from a byte array.
-     * 
+     *
      * @param data A byte array to decode from
      * @return A BER-TLV object decoded
      * @throws ResultException
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
index 60e8148..a27c582 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
@@ -19,7 +19,7 @@
 import android.graphics.Bitmap;
 
 /**
- * Container class for proactive command parameters. 
+ * Container class for proactive command parameters.
  *
  */
 class CommandParams {
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
index eb354e9..06b36a4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
@@ -20,7 +20,7 @@
 import android.os.Handler;
 import android.os.Message;
 
-import com.android.internal.telephony.gsm.GsmAlphabet;
+import com.android.internal.telephony.GsmAlphabet;
 import com.android.internal.telephony.gsm.SIMFileHandler;
 
 import java.util.Iterator;
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java b/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
index 833ff3c..4f746ac 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
@@ -22,9 +22,9 @@
 
 /**
  * Class for representing COMPREHENSION-TLV objects.
- * 
+ *
  * @see "ETSI TS 101 220 subsection 7.1.1"
- * 
+ *
  * {@hide}
  */
 class ComprehensionTlv {
@@ -38,7 +38,7 @@
      * Constructor. Private on purpose. Use
      * {@link #decodeMany(byte[], int) decodeMany} or
      * {@link #decode(byte[], int) decode} method.
-     * 
+     *
      * @param tag The tag for this object
      * @param cr Comprehension Required flag
      * @param length Length of the value
@@ -76,7 +76,7 @@
 
     /**
      * Parses a list of COMPREHENSION-TLV objects from a byte array.
-     * 
+     *
      * @param data A byte array containing data to be parsed
      * @param startIndex Index in data at which to start parsing
      * @return A list of COMPREHENSION-TLV objects parsed
@@ -97,7 +97,7 @@
 
     /**
      * Parses an COMPREHENSION-TLV object from a byte array.
-     * 
+     *
      * @param data A byte array containing data to be parsed
      * @param startIndex Index in data at which to start parsing
      * @return A COMPREHENSION-TLV object parsed
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java b/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
index a63d1ca..fc02d2a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
@@ -30,9 +30,9 @@
 import java.util.HashMap;
 
 /**
- * Class for loading icons from the SIM card. Has two states: single, for loading 
+ * Class for loading icons from the SIM card. Has two states: single, for loading
  * one icon. Multi, for loading icons list.
- * 
+ *
  */
 class IconLoader extends Handler {
     // members
@@ -51,13 +51,13 @@
 
     private static IconLoader sLoader = null;
 
-    // Loader state values. 
+    // Loader state values.
     private static final int STATE_SINGLE_ICON = 1;
     private static final int STATE_MULTI_ICONS = 2;
 
-    // Finished loading single record from a linear-fixed EF-IMG. 
+    // Finished loading single record from a linear-fixed EF-IMG.
     private static final int EVENT_READ_EF_IMG_RECOED_DONE  = 1;
-    // Finished loading single icon from a Transparent DF-Graphics. 
+    // Finished loading single icon from a Transparent DF-Graphics.
     private static final int EVENT_READ_ICON_DONE           = 2;
     // Finished loading single colour icon lookup table.
     private static final int EVENT_READ_CLUT_DONE           = 3;
@@ -170,10 +170,10 @@
     }
 
     /**
-     * Handles Image descriptor parsing and required processing. This is the 
+     * Handles Image descriptor parsing and required processing. This is the
      * first step required to handle retrieving icons from the SIM.
-     * 
-     * @param data byte [] containing Image Instance descriptor as defined in 
+     *
+     * @param data byte [] containing Image Instance descriptor as defined in
      * TS 51.011.
      */
     private boolean handleImageDescriptor(byte[] rawData) {
@@ -232,7 +232,7 @@
      * @param data The raw data
      * @param length The length of image body
      * @return The bitmap
-     */    
+     */
     public static Bitmap parseToBnW(byte[] data, int length){
         int valueIndex = 0;
         int width = data[valueIndex++] & 0xFF;
@@ -264,7 +264,7 @@
      * 0 is black
      * 1 is white
      * @param bit to decode
-     * @return RGB color  
+     * @return RGB color
      */
     private static int bitToBnW(int bit){
         if(bit == 1){
@@ -276,11 +276,11 @@
 
     /**
      * a TS 131.102 image instance of code scheme '11' into color Bitmap
-     * 
+     *
      * @param data The raw data
      * @param length the length of image body
      * @param transparency with or without transparency
-     * @param clut coulor lookup table 
+     * @param clut coulor lookup table
      * @return The color bitmap
      */
     public static Bitmap parseToRGB(byte[] data, int length,
@@ -321,9 +321,9 @@
         return Bitmap.createBitmap(pixels, width, height,
                 Bitmap.Config.ARGB_8888);
     }
-    
+
     /**
-     * Calculate bit mask for a given number of bits. The mask should enable to 
+     * Calculate bit mask for a given number of bits. The mask should enable to
      * make a bitwise and to the given number of bits.
      * @param numOfBits number of bits to calculate mask for.
      * @return bit mask
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java b/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java
index 7120a37..880b9e5 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java
@@ -33,7 +33,8 @@
     static final int CODING_SCHEME_BASIC = 0x11;
     static final int CODING_SCHEME_COLOUR = 0x21;
 
-    public static final int ID_LENGTH = 9;
+    // public static final int ID_LENGTH = 9;
+    // ID_LENGTH substituted by IccFileHandlerBase.GET_RESPONSE_EF_IMG_SIZE_BYTES
 
     ImageDescriptor() {
         width = 0;
@@ -47,7 +48,7 @@
 
     /**
      * Extract descriptor information about image instance.
-     * 
+     *
      * @param rawData
      * @param valueIndex
      * @return ImageDescriptor
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java b/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
index 9afa063..810afd2 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.gsm.stk;
 
-import com.android.internal.telephony.gsm.EncodeException;
-import com.android.internal.telephony.gsm.GsmAlphabet;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
 
 import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
index 5d82473..1cf38ed 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
@@ -17,7 +17,7 @@
 package com.android.internal.telephony.gsm.stk;
 
 import com.android.internal.telephony.gsm.SIMFileHandler;
-import com.android.internal.telephony.gsm.SimUtils;
+import com.android.internal.telephony.IccUtils;
 
 import android.os.Handler;
 import android.os.HandlerState;
@@ -142,7 +142,7 @@
         case StkService.MSG_ID_REFRESH:
             byte[] rawData = null;
             try {
-                rawData = SimUtils.hexStringToBytes((String) rilMsg.mData);
+                rawData = IccUtils.hexStringToBytes((String) rilMsg.mData);
             } catch (Exception e) {
                 // zombie messages are dropped
                 StkLog.d(this, "decodeMessageParams dropping zombie messages");
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
index c0c4ceb..3de14f0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
@@ -23,11 +23,13 @@
 import android.os.HandlerThread;
 import android.os.Message;
 
-import com.android.internal.telephony.gsm.CommandsInterface;
-import com.android.internal.telephony.gsm.GsmSimCard;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.gsm.SimCard;
 import com.android.internal.telephony.gsm.SIMFileHandler;
 import com.android.internal.telephony.gsm.SIMRecords;
-import com.android.internal.telephony.gsm.SimUtils;
 
 import android.util.Config;
 
@@ -115,10 +117,12 @@
  */
 public class StkService extends Handler implements AppInterface {
 
+    // Class members
+    private static SIMRecords mSimRecords;
+    
     // Service members.
     private static StkService sInstance;
     private CommandsInterface mCmdIf;
-    private SIMRecords mSimRecords;
     private Context mContext;
     private StkCmdMessage mCurrntCmd = null;
     private StkCmdMessage mMenuCmd = null;
@@ -147,7 +151,7 @@
 
     /* Intentionally private for singleton */
     private StkService(CommandsInterface ci, SIMRecords sr, Context context,
-            SIMFileHandler fh, GsmSimCard sc) {
+            SIMFileHandler fh, SimCard sc) {
         if (ci == null || sr == null || context == null || fh == null
                 || sc == null) {
             throw new NullPointerException(
@@ -172,6 +176,23 @@
         mSimRecords.registerForRecordsLoaded(this, MSG_ID_SIM_LOADED, null);
     }
 
+    public void dispose() {
+        mSimRecords.unregisterForRecordsLoaded(this);
+        mCmdIf.unSetOnStkSessionEnd(this);
+        mCmdIf.unSetOnStkProactiveCmd(this);
+        mCmdIf.unSetOnStkEvent(this);
+        mCmdIf.unSetOnStkCallSetUp(this);
+
+        this.removeCallbacksAndMessages(null);
+
+        //removing instance
+        sInstance = null;
+    }
+
+    protected void finalize() {
+        StkLog.d(this, "Service finalized");
+    }
+
     private void handleRilMsg(RilMessage rilMsg) {
         if (rilMsg == null) {
             return;
@@ -334,7 +355,7 @@
         }
 
         byte[] rawData = buf.toByteArray();
-        String hexString = SimUtils.bytesToHexString(rawData);
+        String hexString = IccUtils.bytesToHexString(rawData);
         if (Config.LOGD) {
             StkLog.d(this, "TERMINAL RESPONSE: " + hexString);
         }
@@ -380,7 +401,7 @@
         int len = rawData.length - 2; // minus (tag + length)
         rawData[1] = (byte) len;
 
-        String hexString = SimUtils.bytesToHexString(rawData);
+        String hexString = IccUtils.bytesToHexString(rawData);
 
         mCmdIf.sendEnvelope(hexString, null);
     }
@@ -423,7 +444,7 @@
         int len = rawData.length - 2; // minus (tag + length)
         rawData[1] = (byte) len;
 
-        String hexString = SimUtils.bytesToHexString(rawData);
+        String hexString = IccUtils.bytesToHexString(rawData);
 
         mCmdIf.sendEnvelope(hexString, null);
     }
@@ -439,7 +460,7 @@
      * @return The only Service object in the system
      */
     public static StkService getInstance(CommandsInterface ci, SIMRecords sr,
-            Context context, SIMFileHandler fh, GsmSimCard sc) {
+            Context context, SIMFileHandler fh, SimCard sc) {
         if (sInstance == null) {
             if (ci == null || sr == null || context == null || fh == null
                     || sc == null) {
@@ -448,6 +469,17 @@
             HandlerThread thread = new HandlerThread("Stk Telephony service");
             thread.start();
             sInstance = new StkService(ci, sr, context, fh, sc);
+            StkLog.d(sInstance, "NEW sInstance");
+        } else if ((sr != null) && (mSimRecords != sr)) {
+            StkLog.d(sInstance, String.format(
+                    "Reinitialize the Service with SIMRecords sr=0x%x.", sr));
+            mSimRecords = sr;
+
+            // re-Register for SIM ready event.
+            mSimRecords.registerForRecordsLoaded(sInstance, MSG_ID_SIM_LOADED, null);
+            StkLog.d(sInstance, "sr changed reinitialize and return current sInstance");
+        } else {
+            StkLog.d(sInstance, "Return current sInstance");
         }
         return sInstance;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java b/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
index 2cf87ba..8c8f977 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.gsm.stk;
 
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.SimUtils;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccUtils;
 import com.android.internal.telephony.gsm.stk.Duration.TimeUnit;
 
 import java.io.UnsupportedEncodingException;
@@ -117,7 +117,7 @@
 
             try {
                 int id = rawValue[valueIndex] & 0xff;
-                String text = SimUtils.adnStringFieldToString(rawValue,
+                String text = IccUtils.adnStringFieldToString(rawValue,
                         valueIndex + 1, textLen);
                 item = new Item(id, text);
             } catch (IndexOutOfBoundsException e) {
@@ -278,7 +278,7 @@
         int length = ctlv.getLength();
         if (length != 0) {
             try {
-                return SimUtils.adnStringFieldToString(rawValue, valueIndex,
+                return IccUtils.adnStringFieldToString(rawValue, valueIndex,
                         length);
             } catch (IndexOutOfBoundsException e) {
                 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index 33c1679..cb09cea 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -23,19 +23,18 @@
 import android.os.Message;
 import android.util.Log;
 
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.BaseCommands;
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.gsm.CallFailCause;
-import com.android.internal.telephony.gsm.CommandException;
-import com.android.internal.telephony.gsm.CommandsInterface;
 import com.android.internal.telephony.gsm.PDPContextState;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.Phone;
 
 import java.util.ArrayList;
 
 public final class SimulatedCommands extends BaseCommands
-        implements CommandsInterface, SimulatedRadioControl
-{
+        implements CommandsInterface, SimulatedRadioControl {
     private final static String LOG_TAG = "SIM";
 
     private enum SimLockState {
@@ -43,14 +42,14 @@
         REQUIRE_PIN,
         REQUIRE_PUK,
         SIM_PERM_LOCKED
-    };
+    }
 
     private enum SimFdnState {
         NONE,
         REQUIRE_PIN2,
         REQUIRE_PUK2,
         SIM_PERM_LOCKED
-    };
+    }
 
     private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE;
     private final static String DEFAULT_SIM_PIN_CODE = "1234";
@@ -103,11 +102,10 @@
 
     //***** CommandsInterface implementation
 
-    public void getSimStatus(Message result)
-    {
+    public void getIccStatus(Message result) {
         switch (mState) {
             case SIM_READY:
-                resultSuccess(result, SimStatus.SIM_READY);
+                resultSuccess(result, IccStatus.ICC_READY);
                 break;
 
             case SIM_LOCKED_OR_ABSENT:
@@ -115,7 +113,7 @@
                 break;
 
             default:
-                resultSuccess(result, SimStatus.SIM_NOT_READY);
+                resultSuccess(result, IccStatus.ICC_NOT_READY);
                 break;
         }
     }
@@ -123,13 +121,13 @@
     private void returnSimLockedStatus(Message result) {
         switch (mSimLockedState) {
             case REQUIRE_PIN:
-                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: SIM_PIN");
-                resultSuccess(result, SimStatus.SIM_PIN);
+                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: ICC_PIN");
+                resultSuccess(result, IccStatus.ICC_PIN);
                 break;
 
             case REQUIRE_PUK:
-                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: SIM_PUK");
-                resultSuccess(result, SimStatus.SIM_PUK);
+                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: ICC_PUK");
+                resultSuccess(result, IccStatus.ICC_PUK);
                 break;
 
             default:
@@ -139,9 +137,9 @@
         }
     }
 
-    public void supplySimPin(String pin, Message result)  {
+    public void supplyIccPin(String pin, Message result)  {
         if (mSimLockedState != SimLockState.REQUIRE_PIN) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin: wrong state, state=" +
                     mSimLockedState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -151,7 +149,7 @@
         }
 
         if (pin != null && pin.equals(mPinCode)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin: success!");
             setRadioState(RadioState.SIM_READY);
             mPinUnlockAttempts = 0;
             mSimLockedState = SimLockState.NONE;
@@ -167,10 +165,10 @@
         if (result != null) {
             mPinUnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin: failed! attempt=" +
                     mPinUnlockAttempts);
             if (mPinUnlockAttempts >= 3) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPin: set state to REQUIRE_PUK");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPin: set state to REQUIRE_PUK");
                 mSimLockedState = SimLockState.REQUIRE_PUK;
             }
 
@@ -181,9 +179,9 @@
         }
     }
 
-    public void supplySimPuk(String puk, String newPin, Message result)  {
+    public void supplyIccPuk(String puk, String newPin, Message result)  {
         if (mSimLockedState != SimLockState.REQUIRE_PUK) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: wrong state, state=" +
                     mSimLockedState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -193,7 +191,7 @@
         }
 
         if (puk != null && puk.equals(SIM_PUK_CODE)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!");
             setRadioState(RadioState.SIM_READY);
             mSimLockedState = SimLockState.NONE;
             mPukUnlockAttempts = 0;
@@ -209,10 +207,10 @@
         if (result != null) {
             mPukUnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: failed! attempt=" +
                     mPukUnlockAttempts);
             if (mPukUnlockAttempts >= 10) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPuk: set state to SIM_PERM_LOCKED");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: set state to SIM_PERM_LOCKED");
                 mSimLockedState = SimLockState.SIM_PERM_LOCKED;
             }
 
@@ -223,9 +221,9 @@
         }
     }
 
-    public void supplySimPin2(String pin2, Message result)  {
+    public void supplyIccPin2(String pin2, Message result)  {
         if (mSimFdnEnabledState != SimFdnState.REQUIRE_PIN2) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin2: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: wrong state, state=" +
                     mSimFdnEnabledState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -235,7 +233,7 @@
         }
 
         if (pin2 != null && pin2.equals(mPin2Code)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin2: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: success!");
             mPin2UnlockAttempts = 0;
             mSimFdnEnabledState = SimFdnState.NONE;
 
@@ -250,10 +248,10 @@
         if (result != null) {
             mPin2UnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin2: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: failed! attempt=" +
                     mPin2UnlockAttempts);
             if (mPin2UnlockAttempts >= 3) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPin2: set state to REQUIRE_PUK2");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: set state to REQUIRE_PUK2");
                 mSimFdnEnabledState = SimFdnState.REQUIRE_PUK2;
             }
 
@@ -264,9 +262,9 @@
         }
     }
 
-    public void supplySimPuk2(String puk2, String newPin2, Message result)  {
+    public void supplyIccPuk2(String puk2, String newPin2, Message result)  {
         if (mSimFdnEnabledState != SimFdnState.REQUIRE_PUK2) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: wrong state, state=" +
                     mSimLockedState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -276,7 +274,7 @@
         }
 
         if (puk2 != null && puk2.equals(SIM_PUK2_CODE)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: success!");
             mSimFdnEnabledState = SimFdnState.NONE;
             mPuk2UnlockAttempts = 0;
 
@@ -291,10 +289,10 @@
         if (result != null) {
             mPuk2UnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: failed! attempt=" +
                     mPuk2UnlockAttempts);
             if (mPuk2UnlockAttempts >= 10) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: set state to SIM_PERM_LOCKED");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: set state to SIM_PERM_LOCKED");
                 mSimFdnEnabledState = SimFdnState.SIM_PERM_LOCKED;
             }
 
@@ -305,7 +303,7 @@
         }
     }
 
-    public void changeSimPin(String oldPin, String newPin, Message result)  {
+    public void changeIccPin(String oldPin, String newPin, Message result)  {
         if (oldPin != null && oldPin.equals(mPinCode)) {
             mPinCode = newPin;
             if (result != null) {
@@ -317,7 +315,7 @@
         }
 
         if (result != null) {
-            Log.i(LOG_TAG, "[SimCmd] changeSimPin: pin failed!");
+            Log.i(LOG_TAG, "[SimCmd] changeIccPin: pin failed!");
 
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -326,7 +324,7 @@
         }
     }
 
-    public void changeSimPin2(String oldPin2, String newPin2, Message result)  {
+    public void changeIccPin2(String oldPin2, String newPin2, Message result)  {
         if (oldPin2 != null && oldPin2.equals(mPin2Code)) {
             mPin2Code = newPin2;
             if (result != null) {
@@ -338,7 +336,7 @@
         }
 
         if (result != null) {
-            Log.i(LOG_TAG, "[SimCmd] changeSimPin: pin2 failed!");
+            Log.i(LOG_TAG, "[SimCmd] changeIccPin2: pin2 failed!");
 
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -348,14 +346,12 @@
     }
 
     public void
-    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result)
-    {
+    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) {
         unimplemented(result);
     }
 
     public void
-    setSuppServiceNotifications(boolean enable, Message result)
-    {
+    setSuppServiceNotifications(boolean enable, Message result) {
         resultSuccess(result, null);
         
         if (enable && mSsnNotifyOn) {
@@ -477,8 +473,7 @@
      *  ar.result contains a List of DriverCall
      *      The ar.result List is sorted by DriverCall.index
      */
-    public void getCurrentCalls (Message result)  
-    {
+    public void getCurrentCalls (Message result) {
         if (mState == RadioState.SIM_READY) {
             //Log.i("GSM", "[SimCmds] getCurrentCalls");
             resultSuccess(result, simulatedCallState.getDriverCalls());
@@ -491,14 +486,20 @@
     }
 
     /** 
+     *  @deprecated
+     */
+    public void getPDPContextList(Message result) {
+        getDataCallList(result);
+    }
+
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result contains a List of PDPContextState
      */
-    public void getPDPContextList(Message result)  
-    {
+    public void getDataCallList(Message result) {
         resultSuccess(result, new ArrayList<PDPContextState>(0));
     }
 
@@ -513,8 +514,7 @@
      * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation)
      * CLIR_INVOCATION  == on "CLIR invocation" (restrict CLI presentation)
      */
-    public void dial (String address, int clirMode, Message result)  
-    {
+    public void dial (String address, int clirMode, Message result) {
         simulatedCallState.onDial(address);
 
         resultSuccess(result, null);
@@ -527,8 +527,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is String containing IMSI on success
      */
-    public void getIMSI(Message result)  
-    {
+    public void getIMSI(Message result) {
         resultSuccess(result, "012345678901234");
     }
 
@@ -539,8 +538,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is String containing IMEI on success
      */
-    public void getIMEI(Message result)  
-    {
+    public void getIMEI(Message result) {
         resultSuccess(result, "012345678901234");
     }
 
@@ -551,8 +549,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is String containing IMEISV on success
      */
-    public void getIMEISV(Message result)  
-    {
+    public void getIMEISV(Message result) {
         resultSuccess(result, "99");
     }
 
@@ -567,8 +564,7 @@
      *  3GPP 22.030 6.5.5
      *  "Releases a specific active call X"
      */
-    public void hangupConnection (int gsmIndex, Message result) 
-    {
+    public void hangupConnection (int gsmIndex, Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('1', (char)('0'+gsmIndex));
@@ -590,8 +586,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void hangupWaitingOrBackground (Message result)
-    {
+    public void hangupWaitingOrBackground (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('0', '\0');
@@ -612,8 +607,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void hangupForegroundResumeBackground (Message result) 
-    {
+    public void hangupForegroundResumeBackground (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('1', '\0');
@@ -634,8 +628,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void switchWaitingOrHoldingAndActive (Message result)
-    {
+    public void switchWaitingOrHoldingAndActive (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('2', '\0');
@@ -655,8 +648,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void conference (Message result)
-    {
+    public void conference (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('3', '\0');
@@ -676,8 +668,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void explicitCallTransfer (Message result)
-    {
+    public void explicitCallTransfer (Message result) {
         boolean success;
 
         success = simulatedCallState.onChld('4', '\0');
@@ -694,8 +685,7 @@
      * "Places all active calls on hold except call X with which 
      *  communication shall be supported."
      */
-    public void separateConnection (int gsmIndex, Message result) 
-    {
+    public void separateConnection (int gsmIndex, Message result) {
         boolean success;
 
         char ch = (char)(gsmIndex + '0');
@@ -714,8 +704,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void acceptCall (Message result) 
-    {
+    public void acceptCall (Message result) {
         boolean success;
         
         success = simulatedCallState.onAnswer();
@@ -733,8 +722,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void rejectCall (Message result)
-    {
+    public void rejectCall (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('0', '\0');
@@ -754,17 +742,22 @@
      * - Any defined in 22.001 F.4 (for generating busy/congestion)
      * - Cause 68: ACM >= ACMMax
      */
-    public void getLastCallFailCause (Message result)
-    {
+    public void getLastCallFailCause (Message result) {
         int[] ret = new int[1];
 
         ret[0] = nextCallFailCause;
         resultSuccess(result, ret);
     }
 
-    public void
-    getLastPdpFailCause (Message result)
-    {
+    /**
+     * @deprecated
+     */
+    public void getLastPdpFailCause (Message result) {
+        unimplemented(result);
+    }
+
+    public void getLastDataCallFailCause(Message result) {
+        //
         unimplemented(result);
     }
 
@@ -779,8 +772,7 @@
      * response.obj.result[1] is  bit error rate (0-7, 99) 
      * as defined in TS 27.007 8.5
      */
-    public void getSignalStrength (Message result)
-    {
+    public void getSignalStrength (Message result) {
         int ret[] = new int[2];
 
         ret[0] = 23;
@@ -840,23 +832,30 @@
     }
 
     /**
-     * response.obj.result is an String[3]
-     * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2
-     * response.obj.result[1] is LAC if registered or NULL if not
-     * response.obj.result[2] is CID if registered or NULL if not
-     * valid LAC are 0x0000 - 0xffff
-     * valid CID are 0x00000000 - 0xffffffff
+     * response.obj.result is an String[14]
+     * See ril.h for details
      *
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" above
      */
-    public void getRegistrationState (Message result)
-    {
-        String ret[] = new String[3];
+    public void getRegistrationState (Message result) {
+        String ret[] = new String[14];
 
         ret[0] = "5"; // registered roam
         ret[1] = null;
         ret[2] = null;
+        ret[3] = null;
+        ret[4] = null;
+        ret[5] = null;
+        ret[6] = null;
+        ret[7] = null;
+        ret[8] = null;
+        ret[9] = null;
+        ret[10] = null;
+        ret[11] = null;
+        ret[12] = null;
+        ret[13] = null;
+        ret[14] = null;
 
         resultSuccess(result, ret);
     }
@@ -878,8 +877,7 @@
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" in the Android telephony system
      */
-    public void getGPRSRegistrationState (Message result)
-    {
+    public void getGPRSRegistrationState (Message result) {
         String ret[] = new String[4];
 
         ret[0] = "5"; // registered roam
@@ -896,8 +894,7 @@
      * response.obj.result[1] is short alpha or null if unregistered
      * response.obj.result[2] is numeric or null if unregistered
      */ 
-    public void getOperator(Message result)
-    {
+    public void getOperator(Message result) {
         String[] ret = new String[3];
 
         ret[0] = "El Telco Loco";
@@ -912,8 +909,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void sendDtmf(char c, Message result)
-    {
+    public void sendDtmf(char c, Message result) {
         resultSuccess(result, null);
     }
 
@@ -922,8 +918,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void startDtmf(char c, Message result)
-    {
+    public void startDtmf(char c, Message result) {
         resultSuccess(result, null);
     }
 
@@ -932,8 +927,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void stopDtmf(Message result)
-    {
+    public void stopDtmf(Message result) {
         resultSuccess(result, null);
     }
 
@@ -950,16 +944,35 @@
         unimplemented(response);
     }
 
+    public void deleteSmsOnRuim(int index, Message response) {
+        Log.d(LOG_TAG, "Delete RUIM message at index " + index);
+        unimplemented(response);
+    }
+
     public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
         Log.d(LOG_TAG, "Write SMS to SIM with status " + status);
         unimplemented(response);
     }
 
+    public void writeSmsToRuim(int status, String pdu, Message response) {
+        Log.d(LOG_TAG, "Write SMS to RUIM with status " + status);
+        unimplemented(response);
+    }
 
     public void setupDefaultPDP(String apn, String user, String password, Message result) {
         unimplemented(result);
     }
 
+    public void setupDataCall(String radioTechnology, String profile, String apn, String user,
+            String password, Message result) {
+        unimplemented(result);
+    }
+
+    public void deactivateDataCall(int cid, Message result) {unimplemented(result);}
+
+    /**
+     * @deprecated
+     */
     public void deactivateDefaultPDP(int cid, Message result) {unimplemented(result);}
 
     public void setPreferredNetworkType(int networkType , Message result) {
@@ -994,9 +1007,8 @@
         }
         return false;
     }
-    
-    public void setRadioPower(boolean on, Message result)
-    {
+
+    public void setRadioPower(boolean on, Message result) {
         if(on) {
             if (isSimLocked()) {
                 Log.i("SIM", "[SimCmd] setRadioPower: SIM locked! state=" +
@@ -1016,12 +1028,16 @@
         unimplemented(result);
     }
 
+    public void acknowledgeLastIncomingCdmaSms(boolean success, Message result) {
+        unimplemented(result);
+    }
+
     /** 
      * parameters equivilient to 27.007 AT+CRSM command 
      * response.obj will be an AsyncResult
      * response.obj.userObj will be a SimIoResult on success
      */
-    public void simIO (int command, int fileid, String path, int p1, int p2,
+    public void iccIO (int command, int fileid, String path, int p1, int p2,
                        int p3, String data, String pin2, Message result) {
         unimplemented(result);
     }
@@ -1069,8 +1085,7 @@
      * @param response is callback message
      */
     
-    public void queryCallWaiting(int serviceClass, Message response)
-    {
+    public void queryCallWaiting(int serviceClass, Message response) {
         unimplemented(response);
     }
     
@@ -1081,8 +1096,7 @@
      */
     
     public void setCallWaiting(boolean enable, int serviceClass,
-            Message response)
-    {
+            Message response) {
         unimplemented(response);
     }
 
@@ -1092,7 +1106,7 @@
      * @param serviceClass is a sum of SERVICE_CLASSS_* 
      */
     public void setCallForward(int action, int cfReason, int serviceClass, 
-                String number, int timeSeconds, Message result) {unimplemented(result);}
+            String number, int timeSeconds, Message result) {unimplemented(result);}
 
     /**
      * cfReason is one of CF_REASON_*
@@ -1103,11 +1117,12 @@
      * An array of length 0 means "disabled for all codes"
      */
     public void queryCallForwardStatus(int cfReason, int serviceClass,
-                String number, Message result) {unimplemented(result);}
+            String number, Message result) {unimplemented(result);}
 
     public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);}
 
-    public void setNetworkSelectionModeManual(String operatorNumeric, Message result) {unimplemented(result);}
+    public void setNetworkSelectionModeManual(
+            String operatorNumeric, Message result) {unimplemented(result);}
 
     /**
      * Queries whether the current network selection mode is automatic
@@ -1117,8 +1132,7 @@
      * a 0 for automatic selection and a 1 for manual selection
      */
 
-    public void getNetworkSelectionMode(Message result)
-    {
+    public void getNetworkSelectionMode(Message result) {
         int ret[] = new int[1];
 
         ret[0] = 0;
@@ -1132,8 +1146,7 @@
      */
     public void getAvailableNetworks(Message result) {unimplemented(result);}
 
-    public void getBasebandVersion (Message result) 
-    {
+    public void getBasebandVersion (Message result) {
         resultSuccess(result, "SimulatedCommands"); 
     }
 
@@ -1172,13 +1185,11 @@
     }
 
 
-    public void resetRadio(Message result)
-    {
+    public void resetRadio(Message result) {
         unimplemented(result);
     }
 
-    public void invokeOemRilRequestRaw(byte[] data, Message response)
-    {
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
         // Just echo back data
         if (response != null) {
             AsyncResult.forMessage(response).result = data;
@@ -1186,8 +1197,7 @@
         }
     }
 
-    public void invokeOemRilRequestStrings(String[] strings, Message response)
-    {
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
         // Just echo back data
         if (response != null) {
             AsyncResult.forMessage(response).result = strings;
@@ -1200,23 +1210,20 @@
     
     /** Start the simulated phone ringing */
     public void
-    triggerRing(String number)
-    {
+    triggerRing(String number) {
         simulatedCallState.triggerRing(number);
         mCallStateRegistrants.notifyRegistrants();
     }
 
     public void
-    progressConnectingCallState()
-    {
+    progressConnectingCallState() {
         simulatedCallState.progressConnectingCallState();
         mCallStateRegistrants.notifyRegistrants();
     }
 
     /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
     public void
-    progressConnectingToActive()
-    {
+    progressConnectingToActive() {
         simulatedCallState.progressConnectingToActive();
         mCallStateRegistrants.notifyRegistrants();
     }
@@ -1225,40 +1232,34 @@
      *  default to true
      */
     public void
-    setAutoProgressConnectingCall(boolean b)
-    {
+    setAutoProgressConnectingCall(boolean b) {
         simulatedCallState.setAutoProgressConnectingCall(b);
     }
 
     public void
-    setNextDialFailImmediately(boolean b)
-    {
+    setNextDialFailImmediately(boolean b) {
         simulatedCallState.setNextDialFailImmediately(b);
     }
 
     public void 
-    setNextCallFailCause(int gsmCause)
-    {
+    setNextCallFailCause(int gsmCause) {
         nextCallFailCause = gsmCause;    
     }
 
     public void
-    triggerHangupForeground()
-    {
+    triggerHangupForeground() {
         simulatedCallState.triggerHangupForeground();
         mCallStateRegistrants.notifyRegistrants();
     }
 
     /** hangup holding calls */
     public void
-    triggerHangupBackground()
-    {
+    triggerHangupBackground() {
         simulatedCallState.triggerHangupBackground();
         mCallStateRegistrants.notifyRegistrants();
     }
 
-    public void triggerSsn(int type, int code)
-    {
+    public void triggerSsn(int type, int code) {
         SuppServiceNotification not = new SuppServiceNotification();
         not.notificationType = type;
         not.code = code;
@@ -1266,8 +1267,7 @@
     }
 
     public void
-    shutdown()
-    {
+    shutdown() {
         setRadioState(RadioState.RADIO_UNAVAILABLE);
         Looper looper = mHandlerThread.getLooper();
         if (looper != null) {
@@ -1278,27 +1278,23 @@
     /** hangup all */
 
     public void
-    triggerHangupAll()
-    {
+    triggerHangupAll() {
         simulatedCallState.triggerHangupAll();
         mCallStateRegistrants.notifyRegistrants();
     }
 
     public void
-    triggerIncomingSMS(String message)
-    {
+    triggerIncomingSMS(String message) {
         //TODO
     }
 
     public void
-    pauseResponses()
-    {
+    pauseResponses() {
         pausedResponseCount++;
     }
 
     public void
-    resumeResponses()
-    {
+    resumeResponses() {
         pausedResponseCount--;
 
         if (pausedResponseCount == 0) {
@@ -1313,8 +1309,7 @@
 
     //***** Private Methods
 
-    private void unimplemented(Message result)
-    {
+    private void unimplemented(Message result) {
         if (result != null) {
             AsyncResult.forMessage(result).exception 
                 = new RuntimeException("Unimplemented");
@@ -1327,8 +1322,7 @@
         }
     }
 
-    private void resultSuccess(Message result, Object ret)
-    {
+    private void resultSuccess(Message result, Object ret) {
         if (result != null) {
             AsyncResult.forMessage(result).result = ret;
             if (pausedResponseCount > 0) {
@@ -1339,8 +1333,7 @@
         }
     }
 
-    private void resultFail(Message result, Throwable tr)
-    {
+    private void resultFail(Message result, Throwable tr) {
         if (result != null) {
             AsyncResult.forMessage(result).exception = tr;
             if (pausedResponseCount > 0) {
@@ -1351,4 +1344,103 @@
         }
     }
 
+    // ***** Methods for CDMA support
+    public void
+    getDeviceIdentity(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void 
+    getCDMASubscription(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void 
+    setCdmaSubscription(int cdmaSubscriptionType, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void queryCdmaRoamingPreference(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void
+    setPhoneType(int phoneType) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+    }
+
+    public void getPreferredVoicePrivacy(Message result) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(result);
+    }
+
+    public void setPreferredVoicePrivacy(boolean enable, Message result) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(result);
+    }
+
+    /**
+     *  Set the TTY mode for the CDMA phone
+     *
+     * @param enable is true to enable, false to disable
+     * @param serviceClass is a sum of SERVICE_CLASS_*
+     * @param response is callback message
+     */
+    public void setTTYModeEnabled(boolean enable, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    /**
+     *  Query the TTY mode for the CDMA phone
+     * (AsyncResult)response.obj).result is an int[] with element [0] set to
+     * 0 for disabled, 1 for enabled. 
+     *  
+     * @param serviceClass is a sum of SERVICE_CLASS_*
+     * @param response is callback message
+     */
+    public void queryTTYModeEnabled(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void sendCDMAFeatureCode(String FeatureCode, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void sendCdmaSms(byte[] pdu, Message response){
+       Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+    }
+
+    public void activateCdmaBroadcastSms(int activate, Message result) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void getCdmaBroadcastConfig(Message result) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setCdmaBroadcastConfig(int[] configValuesArray, Message result) {
+        // TODO Auto-generated method stub
+
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java b/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
index 340d788..803735c 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
@@ -21,14 +21,13 @@
 import android.os.Handler;
 import android.telephony.PhoneNumberUtils;
 import com.android.internal.telephony.ATParseEx;
-import com.android.internal.telephony.gsm.DriverCall;
+import com.android.internal.telephony.DriverCall;
 import java.util.List;
 import java.util.ArrayList;
 
 import android.util.Log;
 
-class CallInfo
-{
+class CallInfo {
     enum State {
         ACTIVE(0),
         HOLDING(1),
@@ -49,8 +48,7 @@
     String number;
     int TOA;
 
-    CallInfo (boolean isMT, State state, boolean isMpty, String number)
-    {
+    CallInfo (boolean isMT, State state, boolean isMpty, String number) {
         this.isMT = isMT;
         this.state = state;
         this.isMpty = isMpty;
@@ -64,20 +62,17 @@
     }
 
     static CallInfo
-    createOutgoingCall(String number)
-    {
+    createOutgoingCall(String number) {
         return new CallInfo (false, State.DIALING, false, number);
     }
 
     static CallInfo
-    createIncomingCall(String number)
-    {
+    createIncomingCall(String number) {
         return new CallInfo (true, State.INCOMING, false, number);
     }
 
     String
-    toCLCCLine(int index)
-    {
+    toCLCCLine(int index) {
         return 
             "+CLCC: "
             + index + "," + (isMT ? "1" : "0") +","
@@ -86,8 +81,7 @@
     }
 
     DriverCall
-    toDriverCall(int index)
-    {
+    toDriverCall(int index) {
         DriverCall ret; 
 
         ret = new DriverCall();
@@ -112,36 +106,30 @@
 
 
     boolean
-    isActiveOrHeld()
-    {
+    isActiveOrHeld() {
         return state == State.ACTIVE || state == State.HOLDING;
     }
 
     boolean
-    isConnecting()
-    {
+    isConnecting() {
         return state == State.DIALING || state == State.ALERTING;
     }
 
     boolean
-    isRinging()
-    {
+    isRinging() {
         return state == State.INCOMING || state == State.WAITING;
     }
 
 }
 
-class InvalidStateEx extends Exception
-{
-    InvalidStateEx()
-    {
+class InvalidStateEx extends Exception {
+    InvalidStateEx() {
 
     }
 }
 
 
-class SimulatedGsmCallState extends Handler
-{
+class SimulatedGsmCallState extends Handler {
     //***** Instance Variables
 
     CallInfo calls[] = new CallInfo[MAX_CALLS];
@@ -168,8 +156,7 @@
     }
 
     public void
-    handleMessage(Message msg)
-    {
+    handleMessage(Message msg) {
         synchronized(this) { switch (msg.what) {
             // PLEASE REMEMBER
             // calls may have hung up by the time delayed events happen
@@ -181,15 +168,13 @@
     }
 
     //***** Public Methods
-   
-    
+
     /** 
      * Start the simulated phone ringing 
      * true if succeeded, false if failed
      */
     public boolean
-    triggerRing(String number)
-    {
+    triggerRing(String number) {
         synchronized (this) {
             int empty = -1;
             boolean isCallWaiting = false;
@@ -230,8 +215,7 @@
 
     /** If a call is DIALING or ALERTING, progress it to the next state */
     public void
-    progressConnectingCallState()
-    {
+    progressConnectingCallState() {
         synchronized (this)  {
             for (int i = 0 ; i < calls.length ; i++) {
                 CallInfo call = calls[i];
@@ -257,8 +241,7 @@
 
     /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
     public void
-    progressConnectingToActive()
-    {
+    progressConnectingToActive() {
         synchronized (this)  {
             for (int i = 0 ; i < calls.length ; i++) {
                 CallInfo call = calls[i];
@@ -277,14 +260,12 @@
      *  default to true
      */
     public void
-    setAutoProgressConnectingCall(boolean b)
-    {        
+    setAutoProgressConnectingCall(boolean b) {
         autoProgressConnecting = b;
     }
     
     public void
-    setNextDialFailImmediately(boolean b)
-    {
+    setNextDialFailImmediately(boolean b) {
         nextDialFailImmediately = b;
     }
 
@@ -293,8 +274,7 @@
      * returns true if call was hung up, false if not
      */
     public boolean
-    triggerHangupForeground()
-    {
+    triggerHangupForeground() {
         synchronized (this) {
             boolean found;
 
@@ -333,8 +313,7 @@
      * returns true if call was hung up, false if not
      */
     public boolean
-    triggerHangupBackground()
-    {
+    triggerHangupBackground() {
         synchronized (this) {
             boolean found = false;
 
@@ -356,8 +335,7 @@
      * returns true if call was hung up, false if not
      */
     public boolean
-    triggerHangupAll()
-    {
+    triggerHangupAll() {
         synchronized(this) {
             boolean found = false;
 
@@ -376,8 +354,7 @@
     }
 
     public boolean
-    onAnswer()
-    {
+    onAnswer() {
         synchronized (this) {
             for (int i = 0 ; i < calls.length ; i++) {
                 CallInfo call = calls[i];
@@ -395,8 +372,7 @@
     }
 
     public boolean
-    onHangup()
-    {
+    onHangup() {
         boolean found = false;
 
         for (int i = 0 ; i < calls.length ; i++) {
@@ -412,8 +388,7 @@
     }
 
     public boolean
-    onChld(char c0, char c1)
-    {
+    onChld(char c0, char c1) {
         boolean ret;
         int callIndex = 0;
 
@@ -499,8 +474,7 @@
 
 
     public boolean
-    releaseActiveAcceptHeldOrWaiting()
-    {
+    releaseActiveAcceptHeldOrWaiting() {
         boolean foundHeld = false;
         boolean foundActive = false;
 
@@ -555,8 +529,7 @@
     }
 
     public boolean
-    switchActiveAndHeldOrWaiting()
-    {
+    switchActiveAndHeldOrWaiting() {
         boolean hasHeld = false;
         
         // first, are there held calls?
@@ -589,8 +562,7 @@
 
 
     public boolean
-    separateCall(int index)
-    {
+    separateCall(int index) {
         try {
             CallInfo c;
 
@@ -631,8 +603,7 @@
 
 
     public boolean
-    conference() 
-    {
+    conference() {
         int countCalls = 0;
 
         // if there's connecting calls, we can't do this yet
@@ -662,8 +633,7 @@
     }
 
     public boolean
-    explicitCallTransfer()
-    {
+    explicitCallTransfer() {
         int countCalls = 0;
 
         // if there's connecting calls, we can't do this yet
@@ -684,8 +654,7 @@
     }
 
     public boolean
-    onDial(String address)
-    {
+    onDial(String address) {
         CallInfo call;
         int freeSlot = -1;
 
@@ -758,8 +727,7 @@
     }
 
     public List<DriverCall>
-    getDriverCalls()
-    {
+    getDriverCalls() {
         ArrayList<DriverCall> ret = new ArrayList<DriverCall>(calls.length);
 
         for (int i = 0 ; i < calls.length ; i++) {
@@ -779,8 +747,7 @@
     }
 
     public List<String>
-    getClccLines()
-    {
+    getClccLines() {
         ArrayList<String> ret = new ArrayList<String>(calls.length);
 
         for (int i = 0 ; i < calls.length ; i++) {
@@ -795,8 +762,7 @@
     }
 
     private int
-    countActiveLines() throws InvalidStateEx
-    {
+    countActiveLines() throws InvalidStateEx {
         boolean hasMpty = false;
         boolean hasHeld = false;
         boolean hasActive = false;
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
index 00c1ce8..0fc3d16 100644
--- a/test-runner/android/test/TestLocationProvider.java
+++ b/test-runner/android/test/TestLocationProvider.java
@@ -18,11 +18,13 @@
 
 
 import android.location.Criteria;
+import android.location.ILocationManager;
 import android.location.Location;
-import android.location.LocationProviderImpl;
 import android.os.Bundle;
 import android.os.SystemClock;
 
+import com.android.internal.location.LocationProviderImpl;
+
 /**
  * @hide - This is part of a framework that is under development and should not be used for
  * active development.
@@ -36,14 +38,45 @@
     public static final float SPEED = 10;
     public static final float BEARING = 1;
     public static final int STATUS = AVAILABLE;
+    private static final long LOCATION_INTERVAL = 1000;
 
     private Location mLocation;
     private boolean mEnabled;
+    private TestLocationProviderThread mThread;
 
-    public TestLocationProvider() {
-        super(PROVIDER_NAME);
+    private class TestLocationProviderThread extends Thread {
+
+        private boolean mDone = false;
+
+        public TestLocationProviderThread() {
+            super("TestLocationProviderThread");
+        }
+
+        public void run() {            
+            // thread exits after disable() is called
+            synchronized (this) {
+                while (!mDone) {
+                    try {
+                        wait(LOCATION_INTERVAL);
+                    } catch (InterruptedException e) {
+                    }
+                    
+                    if (!mDone) {
+                        TestLocationProvider.this.updateLocation();
+                    }
+                }
+            }
+        }
+        
+        synchronized void setDone() {
+            mDone = true;
+            notify();
+        }
+    }
+
+    public TestLocationProvider(ILocationManager locationManager) {
+        super(PROVIDER_NAME, locationManager);
         mLocation = new Location(PROVIDER_NAME);
-        updateLocation();
     }
 
     //LocationProvider methods
@@ -95,13 +128,23 @@
 
     //LocationProviderImpl methods
     @Override
-    public void disable() {
+    public synchronized void disable() {
         mEnabled = false;
+        if (mThread != null) {
+            mThread.setDone();
+            try {
+                mThread.join();
+            } catch (InterruptedException e) {
+            }
+            mThread = null;
+        }
     }
 
     @Override
-    public void enable() {
-        mEnabled = true;
+    public synchronized void enable() {
+       mEnabled = true;
+        mThread = new TestLocationProviderThread();
+        mThread.start();
     }
 
     @Override
@@ -110,13 +153,6 @@
     }
 
     @Override
-    public boolean getLocation(Location l) {
-        updateLocation();
-        l.set(mLocation);
-        return true;
-    }
-
-    @Override
     public int getStatus(Bundle extras) {
         return STATUS;
     }
@@ -134,6 +170,7 @@
         extras.putInt("extraTest", 24);
         mLocation.setExtras(extras);
         mLocation.setTime(time);
+        reportLocationChanged(mLocation);
     }
 
 }
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index e733dd1..bd39a14 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -386,4 +386,12 @@
             throws PackageManager.NameNotFoundException {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public float getApplicationScale() {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/tests/AndroidTests/res/values-320x200/configVarying.xml b/tests/AndroidTests/res/values-320x200/configVarying.xml
deleted file mode 100644
index ca2a286..0000000
--- a/tests/AndroidTests/res/values-320x200/configVarying.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
-    <item type="configVarying" name="simple">simple 320x200</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag 320x200</item>
-    </bag>
-</resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-32dpi/configVarying.xml
similarity index 86%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to tests/AndroidTests/res/values-32dpi/configVarying.xml
index 674787e..f903f0f 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-32dpi/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple finger</item>
+    <item type="configVarying" name="simple">simple 32dpi</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
+        <item name="testString">bag 32dpi</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-640x400/configVarying.xml
similarity index 86%
rename from tests/AndroidTests/res/values-finger/configVarying.xml
rename to tests/AndroidTests/res/values-640x400/configVarying.xml
index 674787e..30332c0 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-640x400/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple finger</item>
+    <item type="configVarying" name="simple">simple 640x400</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
+        <item name="testString">bag 640x400</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-fr-rFR/configVarying.xml
similarity index 86%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to tests/AndroidTests/res/values-fr-rFR/configVarying.xml
index 674787e..5ecac7c 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-fr-rFR/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple finger</item>
+    <item type="configVarying" name="simple">simple fr FR</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
+        <item name="testString">bag fr FR</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-fr/configVarying.xml
similarity index 86%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to tests/AndroidTests/res/values-fr/configVarying.xml
index 674787e..8413b5a 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-fr/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple finger</item>
+    <item type="configVarying" name="simple">simple fr</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
+        <item name="testString">bag fr</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-keyshidden/configVarying.xml b/tests/AndroidTests/res/values-keyshidden/configVarying.xml
deleted file mode 100644
index fdffc4d..0000000
--- a/tests/AndroidTests/res/values-keyshidden/configVarying.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
-    <item type="configVarying" name="simple">simple keyshidden</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag keyshidden</item>
-    </bag>
-</resources>
diff --git a/tests/AndroidTests/res/values-trackball/configVarying.xml b/tests/AndroidTests/res/values-mcc110-xx/configVarying.xml
similarity index 86%
copy from tests/AndroidTests/res/values-trackball/configVarying.xml
copy to tests/AndroidTests/res/values-mcc110-xx/configVarying.xml
index 0dec300..82e2435 100644
--- a/tests/AndroidTests/res/values-trackball/configVarying.xml
+++ b/tests/AndroidTests/res/values-mcc110-xx/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple trackball</item>
+    <item type="configVarying" name="simple">simple mcc110 xx</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag trackball</item>
+        <item name="testString">bag mcc110 xx</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-mcc112/configVarying.xml
similarity index 86%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to tests/AndroidTests/res/values-mcc112/configVarying.xml
index 674787e..9c05d77 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-mcc112/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple finger</item>
+    <item type="configVarying" name="simple">simple mcc112</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
+        <item name="testString">bag mcc112</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-trackball/configVarying.xml b/tests/AndroidTests/res/values-mnc220-xx/configVarying.xml
similarity index 86%
rename from tests/AndroidTests/res/values-trackball/configVarying.xml
rename to tests/AndroidTests/res/values-mnc220-xx/configVarying.xml
index 0dec300..fbc7888 100644
--- a/tests/AndroidTests/res/values-trackball/configVarying.xml
+++ b/tests/AndroidTests/res/values-mnc220-xx/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple trackball</item>
+    <item type="configVarying" name="simple">simple mnc220 xx</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag trackball</item>
+        <item name="testString">bag mnc220 xx</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-mnc222-32dpi/configVarying.xml
similarity index 85%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to tests/AndroidTests/res/values-mnc222-32dpi/configVarying.xml
index 674787e..03bea33 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-mnc222-32dpi/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple finger</item>
+    <item type="configVarying" name="simple">simple mnc222 32dpi</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
+        <item name="testString">bag mnc222 32dpi</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-mnc223/configVarying.xml
similarity index 86%
copy from tests/AndroidTests/res/values-finger/configVarying.xml
copy to tests/AndroidTests/res/values-mnc223/configVarying.xml
index 674787e..8936cbc 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-mnc223/configVarying.xml
@@ -15,8 +15,8 @@
 -->
 
 <resources>
-    <item type="configVarying" name="simple">simple finger</item>
+    <item type="configVarying" name="simple">simple mnc223</item>
     <bag type="configVarying" name="bag">
-        <item name="testString">bag finger</item>
+        <item name="testString">bag mnc223</item>
     </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-port/configVarying.xml b/tests/AndroidTests/res/values-port/configVarying.xml
deleted file mode 100644
index 0e1f247..0000000
--- a/tests/AndroidTests/res/values-port/configVarying.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
-    <item type="configVarying" name="simple">simple portrait</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag portrait</item>
-    </bag>
-</resources>
diff --git a/tests/AndroidTests/res/values-qwerty/configVarying.xml b/tests/AndroidTests/res/values-qwerty/configVarying.xml
deleted file mode 100644
index 939f682..0000000
--- a/tests/AndroidTests/res/values-qwerty/configVarying.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
-    <item type="configVarying" name="simple">simple qwerty</item>
-    <bag type="configVarying" name="bag">
-        <item name="testString">bag qwerty</item>
-    </bag>
-</resources>
diff --git a/tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java b/tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java
new file mode 100644
index 0000000..a935247
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.unit_tests;
+
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+import com.android.internal.util.HexDump;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import android.util.Log;
+
+public class BitwiseStreamsTest extends AndroidTestCase {
+    private final static String LOG_TAG = "BitwiseStreamsTest";
+
+    @SmallTest
+    public void testOne() throws Exception {
+        int offset = 3;
+        byte[] inBuf = HexDump.hexStringToByteArray("FFDD");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) outStream.write(8, inBuf[i]);
+        byte[] outBuf = outStream.toByteArray();
+        BitwiseInputStream inStream = new BitwiseInputStream(outBuf);
+        byte[] inBufDup = new byte[inBuf.length];
+        inStream.skip(offset);
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+
+    @SmallTest
+    public void testTwo() throws Exception {
+        int offset = 3;
+        byte[] inBuf = HexDump.hexStringToByteArray("11d4f29c0e9ad3c36e72584e064d9b53");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) outStream.write(8, inBuf[i]);
+        BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
+        inStream.skip(offset);
+        byte[] inBufDup = new byte[inBuf.length];
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+
+    @SmallTest
+    public void testThree() throws Exception {
+        int offset = 4;
+        byte[] inBuf = HexDump.hexStringToByteArray("00031040900112488ea794e0");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) outStream.write(8, inBuf[i]);
+        BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
+        inStream.skip(offset);
+        byte[] inBufDup = new byte[inBuf.length];
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+
+    @SmallTest
+    public void testFour() throws Exception {
+        int offset = 7;
+        byte[] inBuf = HexDump.hexStringToByteArray("00031040900112488ea794e0");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) {
+            outStream.write(5, inBuf[i] >>> 3);
+            outStream.write(3, inBuf[i] & 0x07);
+        }
+        BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
+        inStream.skip(offset);
+        byte[] inBufDup = new byte[inBuf.length];
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+
+    @SmallTest
+    public void testFive() throws Exception {
+        int num_runs = 10;
+        long start = android.os.SystemClock.elapsedRealtime();
+        for (int run = 0; run < num_runs; run++) {
+            int offset = run % 8;
+            byte[] inBuf = HexDump.hexStringToByteArray("00031040900112488ea794e0");
+            BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+            outStream.skip(offset);
+            for (int i = 0; i < inBuf.length; i++) {
+                outStream.write(5, inBuf[i] >>> 3);
+                outStream.write(3, inBuf[i] & 0x07);
+            }
+            BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
+            inStream.skip(offset);
+            byte[] inBufDup = new byte[inBuf.length];
+            for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+            assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+        }
+        long end = android.os.SystemClock.elapsedRealtime();
+        Log.d(LOG_TAG, "repeated encode-decode took " + (end - start) + " ms");
+    }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
new file mode 100644
index 0000000..9ff80c7
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.unit_tests;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+import com.android.internal.util.HexDump;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.Iterator;
+
+import android.util.Log;
+
+public class CdmaSmsTest extends AndroidTestCase {
+    private final static String LOG_TAG = "Cdma_Sms_Test";
+
+    private static UserData makeUserData(String msg) {
+        UserData userData = new UserData();
+        byte[] payload;
+        try {
+            payload = GsmAlphabet.stringToGsm7BitPacked(msg);
+            userData.payload = new byte[payload.length - 1];
+            for (int i = 0; i < userData.payload.length; i++) userData.payload[i] = payload[i + 1];
+            userData.numFields = payload[0];
+            userData.paddingBits = (userData.payload.length * 8) - (userData.numFields * 7);
+            userData.paddingBits = 0; // XXX this is better, wtf?
+            userData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+        } catch (com.android.internal.telephony.EncodeException ex) {
+            assertEquals(1, 0);
+        }
+        return userData;
+    }
+
+    @SmallTest
+    public void testStandardSms() throws Exception {
+        String pdu = "00031040900112488ea794e074d69e1b7392c270326cde9e98";
+        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+        assertEquals("Test standard SMS", bearerData.userData.payloadStr);
+    }
+
+    @SmallTest
+    public void testStandardSmsFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        String payloadStr = "Test standard SMS";
+        bearerData.userData = makeUserData(payloadStr);
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+        assertEquals(0, revBearerData.messageId);
+        assertEquals(false, revBearerData.hasUserDataHeader);
+        assertEquals(UserData.ENCODING_GSM_7BIT_ALPHABET, revBearerData.userData.msgEncoding);
+        assertEquals(payloadStr.length(), revBearerData.userData.numFields);
+        assertEquals(payloadStr, revBearerData.userData.payloadStr);
+    }
+
+    @SmallTest
+    public void testAltUserDataFeedback() throws Exception {
+        try {
+            BearerData bearerData = new BearerData();
+            bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+            bearerData.messageId = 0;
+            bearerData.hasUserDataHeader = false;
+            UserData userData = new UserData();
+            String str1 = "test ascii user data encoding";
+            userData.payload = str1.getBytes("US-ASCII");
+            userData.numFields = str1.length();
+            userData.paddingBits = 0;
+            userData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
+            bearerData.userData = userData;
+            byte []encodedSms = BearerData.encode(bearerData);
+            BearerData revBearerData = BearerData.decode(encodedSms);
+            assertEquals(str1, revBearerData.userData.payloadStr);
+            String str2 = "\u0160u\u1E5B\u0301r\u1ECFg\uD835\uDC1At\u00E9\u4E002\u3042";
+            userData.payload = str2.getBytes("UTF-16");
+            userData.numFields = str2.length() + 1;
+            userData.msgEncoding = UserData.ENCODING_UNICODE_16;
+            encodedSms = BearerData.encode(bearerData);
+            revBearerData = BearerData.decode(encodedSms);
+            assertEquals(str2, revBearerData.userData.payloadStr);
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new RuntimeException("user data encoding error");
+        }
+    }
+
+    @SmallTest
+    public void testReplyOption() throws Exception {
+        String pdu1 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87450080a0180";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals("Test Acknowledgement 1", bd1.userData.payloadStr);
+        assertEquals(true, bd1.userAckReq);
+        assertEquals(false, bd1.deliveryAckReq);
+        assertEquals(false, bd1.readAckReq);
+        assertEquals(false, bd1.reportReq);
+        String pdu2 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87490080a0140";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals("Test Acknowledgement 2", bd2.userData.payloadStr);
+        assertEquals(false, bd2.userAckReq);
+        assertEquals(true, bd2.deliveryAckReq);
+        assertEquals(false, bd2.readAckReq);
+        assertEquals(false, bd2.reportReq);
+        String pdu3 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d874d0080a0120";
+        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+        assertEquals("Test Acknowledgement 3", bd3.userData.payloadStr);
+        assertEquals(false, bd3.userAckReq);
+        assertEquals(false, bd3.deliveryAckReq);
+        assertEquals(true, bd3.readAckReq);
+        assertEquals(false, bd3.reportReq);
+        String pdu4 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87510080a0110";
+        BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+        assertEquals("Test Acknowledgement 4", bd4.userData.payloadStr);
+        assertEquals(false, bd4.userAckReq);
+        assertEquals(false, bd4.deliveryAckReq);
+        assertEquals(false, bd4.readAckReq);
+        assertEquals(true, bd4.reportReq);
+    }
+
+    @SmallTest
+    public void testReplyOptionFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test reply option");
+        bearerData.userAckReq = true;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(true, revBearerData.userAckReq);
+        assertEquals(false, revBearerData.deliveryAckReq);
+        assertEquals(false, revBearerData.readAckReq);
+        assertEquals(false, revBearerData.reportReq);
+        bearerData.userAckReq = false;
+        bearerData.deliveryAckReq = true;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(false, revBearerData.userAckReq);
+        assertEquals(true, revBearerData.deliveryAckReq);
+        assertEquals(false, revBearerData.readAckReq);
+        assertEquals(false, revBearerData.reportReq);
+        bearerData.deliveryAckReq = false;
+        bearerData.readAckReq = true;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(false, revBearerData.userAckReq);
+        assertEquals(false, revBearerData.deliveryAckReq);
+        assertEquals(true, revBearerData.readAckReq);
+        assertEquals(false, revBearerData.reportReq);
+        bearerData.readAckReq = false;
+        bearerData.reportReq = true;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(false, revBearerData.userAckReq);
+        assertEquals(false, revBearerData.deliveryAckReq);
+        assertEquals(false, revBearerData.readAckReq);
+        assertEquals(true, revBearerData.reportReq);
+    }
+
+    @SmallTest
+    public void testNumberOfMessages() throws Exception {
+        String pdu1 = "000310409001124896a794e07595f69f199540ea759a0dc8e00b0163";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals("Test Voice mail 99", bd1.userData.payloadStr);
+        assertEquals(99, bd1.numberOfMessages);
+        String pdu2 = "00031040900113489ea794e07595f69f199540ea759a0988c0600b0164";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals("Test Voice mail 100", bd2.userData.payloadStr);
+        assertEquals(100, bd2.numberOfMessages);
+    }
+
+    @SmallTest
+    public void testNumberOfMessagesFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test message count");
+        bearerData.numberOfMessages = 27;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(bearerData.numberOfMessages, revBearerData.numberOfMessages);
+    }
+
+    @SmallTest
+    public void testCallbackNum() throws Exception {
+        String pdu1 = "00031040900112488ea794e070d436cb638bc5e035ce2f97900e06910431323334";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals("Test Callback nbr", bd1.userData.payloadStr);
+        assertEquals(CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR, bd1.callbackNumber.digitMode);
+        assertEquals(CdmaSmsAddress.TON_INTERNATIONAL_OR_IP, bd1.callbackNumber.ton);
+        assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
+        assertEquals(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY, bd1.callbackNumber.numberPlan);
+        assertEquals("1234", bd1.callbackNumber.address);
+    }
+
+    @SmallTest
+    public void testCallbackNumFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test callback number");
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR;
+        addr.ton = CdmaSmsAddress.TON_NATIONAL_OR_EMAIL;
+        addr.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
+        addr.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN;
+        addr.address = "8005551212";
+        addr.numberOfDigits = (byte)addr.address.length();
+        bearerData.callbackNumber = addr;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        CdmaSmsAddress revAddr = revBearerData.callbackNumber;
+        assertEquals(addr.digitMode, revAddr.digitMode);
+        assertEquals(addr.ton, revAddr.ton);
+        assertEquals(addr.numberMode, revAddr.numberMode);
+        assertEquals(addr.numberPlan, revAddr.numberPlan);
+        assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+        assertEquals(addr.address, revAddr.address);
+        addr.address = "8*55#1012";
+        addr.numberOfDigits = (byte)addr.address.length();
+        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        revAddr = revBearerData.callbackNumber;
+        assertEquals(addr.digitMode, revAddr.digitMode);
+        assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+        assertEquals(addr.address, revAddr.address);
+    }
+
+    @SmallTest
+    public void testMsgCenterTimeStampFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test message center timestamp");
+        bearerData.timeStamp = HexDump.hexStringToByteArray("112233445566");
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(HexDump.toHexString(bearerData.timeStamp),
+                     HexDump.toHexString(revBearerData.timeStamp));
+    }
+
+    @SmallTest
+    public void testPrivacyIndicator() throws Exception {
+        String pdu1 = "0003104090010c485f4194dfea34becf61b840090140";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals(bd1.privacy, BearerData.PRIVACY_RESTRICTED);
+        String pdu2 = "0003104090010c485f4194dfea34becf61b840090180";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals(bd2.privacy, BearerData.PRIVACY_CONFIDENTIAL);
+        String pdu3 = "0003104090010c485f4194dfea34becf61b8400901c0";
+        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+        assertEquals(bd3.privacy, BearerData.PRIVACY_SECRET);
+    }
+
+    @SmallTest
+    public void testPrivacyIndicatorFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        String payloadStr = "test privacy indicator";
+        bearerData.userData = makeUserData(payloadStr);
+        bearerData.privacy = BearerData.PRIVACY_SECRET;
+        bearerData.privacyIndicatorSet = true;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.userData.payloadStr, payloadStr);
+        assertEquals(revBearerData.privacyIndicatorSet, true);
+        assertEquals(revBearerData.privacy, BearerData.PRIVACY_SECRET);
+        bearerData.privacy = BearerData.PRIVACY_RESTRICTED;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.privacy, BearerData.PRIVACY_RESTRICTED);
+    }
+
+    @SmallTest
+    public void testMsgDeliveryAlert() throws Exception {
+        String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals(bd1.alert, 0);
+        assertEquals(bd1.userData.payloadStr, "Test Alert 0");
+        String pdu2 = "0003104090010d4866a794e07055965b91d140300c0140";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals(bd2.alert, 1);
+        assertEquals(bd2.userData.payloadStr, "Test Alert 1");
+        String pdu3 = "0003104090010d4866a794e07055965b91d240300c0180";
+        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+        assertEquals(bd3.alert, 2);
+        assertEquals(bd3.userData.payloadStr, "Test Alert 2");
+        String pdu4 = "0003104090010d4866a794e07055965b91d340300c01c0";
+        BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+        assertEquals(bd4.alert, 3);
+        assertEquals(bd4.userData.payloadStr, "Test Alert 3");
+    }
+
+    @SmallTest
+    public void testMsgDeliveryAlertFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        String payloadStr = "test message delivery alert";
+        bearerData.userData = makeUserData(payloadStr);
+        bearerData.alert = BearerData.ALERT_MEDIUM_PRIO;
+        bearerData.alertIndicatorSet = true;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.userData.payloadStr, payloadStr);
+        assertEquals(revBearerData.alertIndicatorSet, true);
+        assertEquals(revBearerData.alert, bearerData.alert);
+        bearerData.alert = BearerData.ALERT_HIGH_PRIO;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.userData.payloadStr, payloadStr);
+        assertEquals(revBearerData.alertIndicatorSet, true);
+        assertEquals(revBearerData.alert, bearerData.alert);
+    }
+
+    @SmallTest
+    public void testLanguageIndicator() throws Exception {
+        String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals(bd1.userData.payloadStr, "Test Language indicator");
+        assertEquals(bd1.language, BearerData.LANGUAGE_ENGLISH);
+        String pdu2 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0106";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals(bd2.userData.payloadStr, "Test Language indicator");
+        assertEquals(bd2.language, BearerData.LANGUAGE_CHINESE);
+    }
+
+    @SmallTest
+    public void testLanguageIndicatorFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        String payloadStr = "test language indicator";
+        bearerData.userData = makeUserData(payloadStr);
+        bearerData.language = BearerData.LANGUAGE_ENGLISH;
+        bearerData.languageIndicatorSet = true;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.userData.payloadStr, payloadStr);
+        assertEquals(revBearerData.languageIndicatorSet, true);
+        assertEquals(revBearerData.language, bearerData.language);
+        bearerData.language = BearerData.LANGUAGE_KOREAN;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.userData.payloadStr, payloadStr);
+        assertEquals(revBearerData.languageIndicatorSet, true);
+        assertEquals(revBearerData.language, bearerData.language);
+    }
+
+    @SmallTest
+    public void testDisplayMode() throws Exception {
+        String pdu1 = "0003104090010c485f4194dfea34becf61b8400f0100";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        //Log.d(LOG_TAG, "bd1 = " + bd1);
+        assertEquals(bd1.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
+        String pdu2 = "0003104090010c485f4194dfea34becf61b8400f0140";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals(bd2.displayMode, BearerData.DISPLAY_MODE_DEFAULT);
+        String pdu3 = "0003104090010c485f4194dfea34becf61b8400f0180";
+        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+        assertEquals(bd3.displayMode, BearerData.DISPLAY_MODE_USER);
+    }
+
+    @SmallTest
+    public void testDisplayModeFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        String payloadStr = "test display mode";
+        bearerData.userData = makeUserData(payloadStr);
+        bearerData.displayMode = BearerData.DISPLAY_MODE_IMMEDIATE;
+        bearerData.displayModeSet = true;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.userData.payloadStr, payloadStr);
+        assertEquals(revBearerData.displayModeSet, true);
+        assertEquals(revBearerData.displayMode, bearerData.displayMode);
+        bearerData.displayMode = BearerData.DISPLAY_MODE_USER;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(revBearerData.userData.payloadStr, payloadStr);
+        assertEquals(revBearerData.displayModeSet, true);
+        assertEquals(revBearerData.displayMode, bearerData.displayMode);
+    }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
index ce0b53d..360352b 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
@@ -16,10 +16,10 @@
 
 package com.android.unit_tests;
 
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.SmsHeader;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.gsm.SmsMessage;
 import com.android.internal.util.HexDump;
-import android.telephony.gsm.SmsMessage;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
index 09e3b02..f3c1542 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
@@ -23,27 +23,11 @@
 import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
 import android.os.ServiceManager;
-import android.server.search.SearchableInfo;
-import android.server.search.SearchableInfo.ActionKeyInfo;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.MoreAsserts;
-import android.test.mock.MockContext;
-import android.test.mock.MockPackageManager;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.AndroidRuntimeException;
-import android.view.KeyEvent;
-
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * To launch this test from the command line:
@@ -52,7 +36,7 @@
  *   -e class com.android.unit_tests.SearchManagerTest \
  *   com.android.unit_tests/android.test.InstrumentationTestRunner
  */
-public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActivity> {
+public class SearchManagerTest extends ActivityInstrumentationTestCase2<LocalActivity> {
     
     // If non-zero, enable a set of tests that start and stop the search manager.
     // This is currently disabled because it's causing an unwanted jump from the unit test
@@ -71,18 +55,6 @@
      * testSearchManagerInvocations()
      *  FIX - make it work again
      *  stress test with a very long string
-     *  
-     * SearchableInfo tests
-     *  Mock the context so I can provide very specific input data
-     *  Confirm OK with "zero" searchables
-     *  Confirm "good" metadata read properly
-     *  Confirm "bad" metadata skipped properly
-     *  Confirm ordering of searchables
-     *  Confirm "good" actionkeys
-     *  confirm "bad" actionkeys are rejected
-     *  confirm XML ordering enforced (will fail today - bug in SearchableInfo)
-     *  findActionKey works
-     *  getIcon works
      * 
      * SearchManager tests
      *  confirm proper identification of "default" activity based on policy, not hardcoded contacts
@@ -195,348 +167,6 @@
             searchManager.stopSearch();
         }
      }
-    
-    /**
-     * The goal of this test is to confirm proper operation of the 
-     * SearchableInfo helper class.
-     * 
-     * TODO:  The metadata source needs to be mocked out because adding
-     * searchability metadata via this test is causing it to leak into the
-     * real system.  So for now I'm just going to test for existence of the
-     * GoogleSearch app (which is searchable).
-     */
-    @LargeTest
-    public void testSearchableGoogleSearch() {
-        // test basic array & hashmap
-        SearchableInfo.buildSearchableList(mContext);
 
-        // test linkage from another activity
-        // TODO inject this via mocking into the package manager.
-        // TODO for now, just check for searchable GoogleSearch app (this isn't really a unit test)
-        ComponentName thisActivity = new ComponentName(
-                "com.android.googlesearch", 
-                "com.android.googlesearch.GoogleSearch");
-
-        SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, thisActivity);
-        assertNotNull(si);
-        assertTrue(si.mSearchable);
-        assertEquals(thisActivity, si.mSearchActivity);
-        
-        Context appContext = si.getActivityContext(mContext);
-        assertNotNull(appContext);
-        MoreAsserts.assertNotEqual(appContext, mContext);
-        assertEquals("Google Search", appContext.getString(si.getHintId()));
-        assertEquals("Google", appContext.getString(si.getLabelId()));
-    }
-    
-    /**
-     * Test that non-searchable activities return no searchable info (this would typically
-     * trigger the use of the default searchable e.g. contacts)
-     */
-    @LargeTest
-    public void testNonSearchable() {
-        // test basic array & hashmap
-        SearchableInfo.buildSearchableList(mContext);
-
-        // confirm that we return null for non-searchy activities
-        ComponentName nonActivity = new ComponentName(
-                            "com.android.unit_tests",
-                            "com.android.unit_tests.NO_SEARCH_ACTIVITY");
-        SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, nonActivity);
-        assertNull(si);
-    }
-    
-    /**
-     * This is an attempt to run the searchable info list with a mocked context.  Here are some
-     * things I'd like to test.
-     *
-     *  Confirm OK with "zero" searchables
-     *  Confirm "good" metadata read properly
-     *  Confirm "bad" metadata skipped properly
-     *  Confirm ordering of searchables
-     *  Confirm "good" actionkeys
-     *  confirm "bad" actionkeys are rejected
-     *  confirm XML ordering enforced (will fail today - bug in SearchableInfo)
-     *  findActionKey works
-     *  getIcon works
-
-     */
-    @LargeTest
-    public void testSearchableMocked() {
-        MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager());
-        MyMockContext mockContext = new MyMockContext(mContext, mockPM);
-        ArrayList<SearchableInfo> searchables;
-        int count;
-
-        // build item list with real-world source data
-        mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH);
-        SearchableInfo.buildSearchableList(mockContext);
-        // tests with "real" searchables (deprecate, this should be a unit test)
-        searchables = SearchableInfo.getSearchablesList();
-        count = searchables.size();
-        assertTrue(count >= 1);         // this isn't really a unit test
-        checkSearchables(searchables);
-
-        // build item list with mocked search data
-        // this round of tests confirms good operations with "zero" searchables found
-        // This should return either a null pointer or an empty list
-        mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO);
-        SearchableInfo.buildSearchableList(mockContext);
-        searchables = SearchableInfo.getSearchablesList();
-        if (searchables != null) {
-            count = searchables.size();
-            assertTrue(count == 0);
-        }
-    }
-    
-    /**
-     * Generic health checker for an array of searchables.
-     * 
-     * This is designed to pass for any semi-legal searchable, without knowing much about
-     * the format of the underlying data.  It's fairly easy for a non-compliant application
-     * to provide meta-data that will pass here (e.g. a non-existent suggestions authority).
-     * 
-     * @param searchables The list of searchables to examine.
-     */
-    private void checkSearchables(ArrayList<SearchableInfo> searchablesList) {
-        assertNotNull(searchablesList);
-        int count = searchablesList.size();
-        for (int ii = 0; ii < count; ii++) {
-            SearchableInfo si = searchablesList.get(ii);
-            assertNotNull(si);
-            assertTrue(si.mSearchable);
-            assertTrue(si.getLabelId() != 0);        // This must be a useable string
-            assertNotEmpty(si.mSearchActivity.getClassName());
-            assertNotEmpty(si.mSearchActivity.getPackageName());
-            if (si.getSuggestAuthority() != null) {
-                // The suggestion fields are largely optional, so we'll just confirm basic health
-                assertNotEmpty(si.getSuggestAuthority());
-                assertNullOrNotEmpty(si.getSuggestPath());
-                assertNullOrNotEmpty(si.getSuggestSelection());
-                assertNullOrNotEmpty(si.getSuggestIntentAction());
-                assertNullOrNotEmpty(si.getSuggestIntentData());
-            }
-            /* Add a way to get the entire action key list, then explicitly test its elements */
-            /* For now, test the most common action key (CALL) */
-            ActionKeyInfo ai = si.findActionKey(KeyEvent.KEYCODE_CALL);
-            if (ai != null) {
-                assertEquals(ai.mKeyCode, KeyEvent.KEYCODE_CALL);
-                // one of these three fields must be non-null & non-empty
-                boolean m1 = (ai.mQueryActionMsg != null) && (ai.mQueryActionMsg.length() > 0);
-                boolean m2 = (ai.mSuggestActionMsg != null) && (ai.mSuggestActionMsg.length() > 0);
-                boolean m3 = (ai.mSuggestActionMsgColumn != null) && 
-                                (ai.mSuggestActionMsgColumn.length() > 0);
-                assertTrue(m1 || m2 || m3);
-            }
-            
-            /* 
-             * Find ways to test these:
-             * 
-             * private int mSearchMode
-             * private Drawable mIcon
-             */
-            
-            /*
-             * Explicitly not tested here:
-             * 
-             * Can be null, so not much to see:
-             * public String mSearchHint
-             * private String mZeroQueryBanner
-             * 
-             * To be deprecated/removed, so don't bother:
-             * public boolean mFilterMode
-             * public boolean mQuickStart
-             * private boolean mIconResized
-             * private int mIconResizeWidth
-             * private int mIconResizeHeight
-             * 
-             * All of these are "internal" working variables, not part of any contract
-             * private ActivityInfo mActivityInfo
-             * private Rect mTempRect
-             * private String mSuggestProviderPackage
-             * private String mCacheActivityContext
-             */
-        }
-    }
-    
-    /**
-     * Combo assert for "string not null and not empty"
-     */
-    private void assertNotEmpty(final String s) {
-        assertNotNull(s);
-        MoreAsserts.assertNotEqual(s, "");
-    }
-    
-    /**
-     * Combo assert for "string null or (not null and not empty)"
-     */
-    private void assertNullOrNotEmpty(final String s) {
-        if (s != null) {
-            MoreAsserts.assertNotEqual(s, "");
-        }
-    }    
-    
-    /**
-     * This is a mock for context.  Used to perform a true unit test on SearchableInfo.
-     * 
-     */
-    private class MyMockContext extends MockContext {
-        
-        protected Context mRealContext;
-        protected PackageManager mPackageManager;
-        
-        /**
-         * Constructor.
-         * 
-         * @param realContext Please pass in a real context for some pass-throughs to function.
-         */
-        MyMockContext(Context realContext, PackageManager packageManager) {
-            mRealContext = realContext;
-            mPackageManager = packageManager;
-        }
-        
-        /**
-         * Resources.  Pass through for now.
-         */
-        @Override
-        public Resources getResources() {
-            return mRealContext.getResources();
-        }
-
-        /**
-         * Package manager.  Pass through for now.
-         */
-        @Override
-        public PackageManager getPackageManager() {
-            return mPackageManager;
-        }
-
-        /**
-         * Package manager.  Pass through for now.
-         */
-        @Override
-        public Context createPackageContext(String packageName, int flags)
-                throws PackageManager.NameNotFoundException {
-            return mRealContext.createPackageContext(packageName, flags);
-        }
-    }
-
-/**
- * This is a mock for package manager.  Used to perform a true unit test on SearchableInfo.
- * 
- */
-    private class MyMockPackageManager extends MockPackageManager {
-        
-        public final static int SEARCHABLES_PASSTHROUGH = 0;
-        public final static int SEARCHABLES_MOCK_ZERO = 1;
-        public final static int SEARCHABLES_MOCK_ONEGOOD = 2;
-        public final static int SEARCHABLES_MOCK_ONEGOOD_ONEBAD = 3;
-        
-        protected PackageManager mRealPackageManager;
-        protected int mSearchablesMode;
-
-        public MyMockPackageManager(PackageManager realPM) {
-            mRealPackageManager = realPM;
-            mSearchablesMode = SEARCHABLES_PASSTHROUGH;
-        }
-
-        /**
-         * Set the mode for various tests.
-         */
-        public void setSearchablesMode(int newMode) {
-            switch (newMode) {
-            case SEARCHABLES_PASSTHROUGH:
-            case SEARCHABLES_MOCK_ZERO:
-                mSearchablesMode = newMode;
-                break;
-                
-            default:
-                throw new UnsupportedOperationException();       
-            }
-        }
-        
-        /**
-         * Find activities that support a given intent.
-         * 
-         * Retrieve all activities that can be performed for the given intent.
-         * 
-         * @param intent The desired intent as per resolveActivity().
-         * @param flags Additional option flags.  The most important is
-         *                    MATCH_DEFAULT_ONLY, to limit the resolution to only
-         *                    those activities that support the CATEGORY_DEFAULT.
-         * 
-         * @return A List<ResolveInfo> containing one entry for each matching
-         *         Activity. These are ordered from best to worst match -- that
-         *         is, the first item in the list is what is returned by
-         *         resolveActivity().  If there are no matching activities, an empty
-         *         list is returned.
-         */
-        @Override 
-        public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
-            assertNotNull(intent);
-            assertEquals(intent.getAction(), Intent.ACTION_SEARCH);
-            switch (mSearchablesMode) {
-            case SEARCHABLES_PASSTHROUGH:
-                return mRealPackageManager.queryIntentActivities(intent, flags);
-            case SEARCHABLES_MOCK_ZERO:
-                return null;
-            default:
-                throw new UnsupportedOperationException();
-            }
-        }
-        
-        /**
-         * Retrieve an XML file from a package.  This is a low-level API used to
-         * retrieve XML meta data.
-         * 
-         * @param packageName The name of the package that this xml is coming from.
-         * Can not be null.
-         * @param resid The resource identifier of the desired xml.  Can not be 0.
-         * @param appInfo Overall information about <var>packageName</var>.  This
-         * may be null, in which case the application information will be retrieved
-         * for you if needed; if you already have this information around, it can
-         * be much more efficient to supply it here.
-         * 
-         * @return Returns an XmlPullParser allowing you to parse out the XML
-         * data.  Returns null if the xml resource could not be found for any
-         * reason.
-         */
-        @Override 
-        public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) {
-            assertNotNull(packageName);
-            MoreAsserts.assertNotEqual(packageName, "");
-            MoreAsserts.assertNotEqual(resid, 0);
-            switch (mSearchablesMode) {
-            case SEARCHABLES_PASSTHROUGH:
-                return mRealPackageManager.getXml(packageName, resid, appInfo);
-            case SEARCHABLES_MOCK_ZERO:
-            default:
-                throw new UnsupportedOperationException();
-            }
-        }
-        
-        /**
-         * Find a single content provider by its base path name.
-         * 
-         * @param name The name of the provider to find.
-         * @param flags Additional option flags.  Currently should always be 0.
-         * 
-         * @return ContentProviderInfo Information about the provider, if found,
-         *         else null.
-         */
-        @Override 
-        public ProviderInfo resolveContentProvider(String name, int flags) {
-            assertNotNull(name);
-            MoreAsserts.assertNotEqual(name, "");
-            assertEquals(flags, 0);
-            switch (mSearchablesMode) {
-            case SEARCHABLES_PASSTHROUGH:
-                return mRealPackageManager.resolveContentProvider(name, flags);
-            case SEARCHABLES_MOCK_ZERO:
-            default:
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
 }
 
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
new file mode 100644
index 0000000..c299b10
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
@@ -0,0 +1,411 @@
+/*
+ * 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;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.server.search.SearchableInfo;
+import android.server.search.Searchables;
+import android.server.search.SearchableInfo.ActionKeyInfo;
+import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+import android.test.mock.MockContext;
+import android.test.mock.MockPackageManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.KeyEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * To launch this test from the command line:
+ * 
+ * adb shell am instrument -w \
+ *   -e class com.android.unit_tests.SearchablesTest \
+ *   com.android.unit_tests/android.test.InstrumentationTestRunner
+ */
+@SmallTest
+public class SearchablesTest extends AndroidTestCase {
+    
+    /*
+     * SearchableInfo tests
+     *  Mock the context so I can provide very specific input data
+     *  Confirm OK with "zero" searchables
+     *  Confirm "good" metadata read properly
+     *  Confirm "bad" metadata skipped properly
+     *  Confirm ordering of searchables
+     *  Confirm "good" actionkeys
+     *  confirm "bad" actionkeys are rejected
+     *  confirm XML ordering enforced (will fail today - bug in SearchableInfo)
+     *  findActionKey works
+     *  getIcon works
+     */
+    
+    /**
+     * The goal of this test is to confirm proper operation of the 
+     * SearchableInfo helper class.
+     * 
+     * TODO:  The metadata source needs to be mocked out because adding
+     * searchability metadata via this test is causing it to leak into the
+     * real system.  So for now I'm just going to test for existence of the
+     * GoogleSearch app (which is searchable).
+     */
+    public void testSearchableGoogleSearch() {
+        // test basic array & hashmap
+        Searchables searchables = new Searchables(mContext);
+        searchables.buildSearchableList();
+
+        // test linkage from another activity
+        // TODO inject this via mocking into the package manager.
+        // TODO for now, just check for searchable GoogleSearch app (this isn't really a unit test)
+        ComponentName thisActivity = new ComponentName(
+                "com.android.googlesearch", 
+                "com.android.googlesearch.GoogleSearch");
+
+        SearchableInfo si = searchables.getSearchableInfo(thisActivity);
+        assertNotNull(si);
+        assertTrue(si.mSearchable);
+        assertEquals(thisActivity, si.mSearchActivity);
+        
+        Context appContext = si.getActivityContext(mContext);
+        assertNotNull(appContext);
+        MoreAsserts.assertNotEqual(appContext, mContext);
+        assertEquals("Google Search", appContext.getString(si.getHintId()));
+        assertEquals("Google", appContext.getString(si.getLabelId()));
+    }
+    
+    /**
+     * Test that non-searchable activities return no searchable info (this would typically
+     * trigger the use of the default searchable e.g. contacts)
+     */
+    public void testNonSearchable() {
+        // test basic array & hashmap
+        Searchables searchables = new Searchables(mContext);
+        searchables.buildSearchableList();
+
+        // confirm that we return null for non-searchy activities
+        ComponentName nonActivity = new ComponentName(
+                            "com.android.unit_tests",
+                            "com.android.unit_tests.NO_SEARCH_ACTIVITY");
+        SearchableInfo si = searchables.getSearchableInfo(nonActivity);
+        assertNull(si);
+    }
+    
+    /**
+     * This is an attempt to run the searchable info list with a mocked context.  Here are some
+     * things I'd like to test.
+     *
+     *  Confirm OK with "zero" searchables
+     *  Confirm "good" metadata read properly
+     *  Confirm "bad" metadata skipped properly
+     *  Confirm ordering of searchables
+     *  Confirm "good" actionkeys
+     *  confirm "bad" actionkeys are rejected
+     *  confirm XML ordering enforced (will fail today - bug in SearchableInfo)
+     *  findActionKey works
+     *  getIcon works
+
+     */
+    public void testSearchableMocked() {
+        MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager());
+        MyMockContext mockContext = new MyMockContext(mContext, mockPM);
+        Searchables searchables;
+        ArrayList<SearchableInfo> searchablesList;
+        int count;
+
+            
+        // build item list with real-world source data
+        mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH);
+        searchables = new Searchables(mockContext);
+        searchables.buildSearchableList();
+        // tests with "real" searchables (deprecate, this should be a unit test)
+        searchablesList = searchables.getSearchablesList();
+        count = searchablesList.size();
+        assertTrue(count >= 1);         // this isn't really a unit test
+        checkSearchables(searchablesList);
+
+        // build item list with mocked search data
+        // this round of tests confirms good operations with "zero" searchables found
+        // This should return either a null pointer or an empty list
+        mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO);
+        searchables = new Searchables(mockContext);
+        searchables.buildSearchableList();
+        searchablesList = searchables.getSearchablesList();
+        if (searchablesList != null) {
+            count = searchablesList.size();
+            assertTrue(count == 0);
+        }
+    }
+    
+    /**
+     * Generic health checker for an array of searchables.
+     * 
+     * This is designed to pass for any semi-legal searchable, without knowing much about
+     * the format of the underlying data.  It's fairly easy for a non-compliant application
+     * to provide meta-data that will pass here (e.g. a non-existent suggestions authority).
+     * 
+     * @param searchables The list of searchables to examine.
+     */
+    private void checkSearchables(ArrayList<SearchableInfo> searchablesList) {
+        assertNotNull(searchablesList);
+        int count = searchablesList.size();
+        for (int ii = 0; ii < count; ii++) {
+            SearchableInfo si = searchablesList.get(ii);
+            assertNotNull(si);
+            assertTrue(si.mSearchable);
+            assertTrue(si.getLabelId() != 0);        // This must be a useable string
+            assertNotEmpty(si.mSearchActivity.getClassName());
+            assertNotEmpty(si.mSearchActivity.getPackageName());
+            if (si.getSuggestAuthority() != null) {
+                // The suggestion fields are largely optional, so we'll just confirm basic health
+                assertNotEmpty(si.getSuggestAuthority());
+                assertNullOrNotEmpty(si.getSuggestPath());
+                assertNullOrNotEmpty(si.getSuggestSelection());
+                assertNullOrNotEmpty(si.getSuggestIntentAction());
+                assertNullOrNotEmpty(si.getSuggestIntentData());
+            }
+            /* Add a way to get the entire action key list, then explicitly test its elements */
+            /* For now, test the most common action key (CALL) */
+            ActionKeyInfo ai = si.findActionKey(KeyEvent.KEYCODE_CALL);
+            if (ai != null) {
+                assertEquals(ai.mKeyCode, KeyEvent.KEYCODE_CALL);
+                // one of these three fields must be non-null & non-empty
+                boolean m1 = (ai.mQueryActionMsg != null) && (ai.mQueryActionMsg.length() > 0);
+                boolean m2 = (ai.mSuggestActionMsg != null) && (ai.mSuggestActionMsg.length() > 0);
+                boolean m3 = (ai.mSuggestActionMsgColumn != null) && 
+                                (ai.mSuggestActionMsgColumn.length() > 0);
+                assertTrue(m1 || m2 || m3);
+            }
+            
+            /* 
+             * Find ways to test these:
+             * 
+             * private int mSearchMode
+             * private Drawable mIcon
+             */
+            
+            /*
+             * Explicitly not tested here:
+             * 
+             * Can be null, so not much to see:
+             * public String mSearchHint
+             * private String mZeroQueryBanner
+             * 
+             * To be deprecated/removed, so don't bother:
+             * public boolean mFilterMode
+             * public boolean mQuickStart
+             * private boolean mIconResized
+             * private int mIconResizeWidth
+             * private int mIconResizeHeight
+             * 
+             * All of these are "internal" working variables, not part of any contract
+             * private ActivityInfo mActivityInfo
+             * private Rect mTempRect
+             * private String mSuggestProviderPackage
+             * private String mCacheActivityContext
+             */
+        }
+    }
+    
+    /**
+     * Combo assert for "string not null and not empty"
+     */
+    private void assertNotEmpty(final String s) {
+        assertNotNull(s);
+        MoreAsserts.assertNotEqual(s, "");
+    }
+    
+    /**
+     * Combo assert for "string null or (not null and not empty)"
+     */
+    private void assertNullOrNotEmpty(final String s) {
+        if (s != null) {
+            MoreAsserts.assertNotEqual(s, "");
+        }
+    }    
+    
+    /**
+     * This is a mock for context.  Used to perform a true unit test on SearchableInfo.
+     * 
+     */
+    private class MyMockContext extends MockContext {
+        
+        protected Context mRealContext;
+        protected PackageManager mPackageManager;
+        
+        /**
+         * Constructor.
+         * 
+         * @param realContext Please pass in a real context for some pass-throughs to function.
+         */
+        MyMockContext(Context realContext, PackageManager packageManager) {
+            mRealContext = realContext;
+            mPackageManager = packageManager;
+        }
+        
+        /**
+         * Resources.  Pass through for now.
+         */
+        @Override
+        public Resources getResources() {
+            return mRealContext.getResources();
+        }
+
+        /**
+         * Package manager.  Pass through for now.
+         */
+        @Override
+        public PackageManager getPackageManager() {
+            return mPackageManager;
+        }
+
+        /**
+         * Package manager.  Pass through for now.
+         */
+        @Override
+        public Context createPackageContext(String packageName, int flags)
+                throws PackageManager.NameNotFoundException {
+            return mRealContext.createPackageContext(packageName, flags);
+        }
+    }
+
+/**
+ * This is a mock for package manager.  Used to perform a true unit test on SearchableInfo.
+ * 
+ */
+    private class MyMockPackageManager extends MockPackageManager {
+        
+        public final static int SEARCHABLES_PASSTHROUGH = 0;
+        public final static int SEARCHABLES_MOCK_ZERO = 1;
+        public final static int SEARCHABLES_MOCK_ONEGOOD = 2;
+        public final static int SEARCHABLES_MOCK_ONEGOOD_ONEBAD = 3;
+        
+        protected PackageManager mRealPackageManager;
+        protected int mSearchablesMode;
+
+        public MyMockPackageManager(PackageManager realPM) {
+            mRealPackageManager = realPM;
+            mSearchablesMode = SEARCHABLES_PASSTHROUGH;
+        }
+
+        /**
+         * Set the mode for various tests.
+         */
+        public void setSearchablesMode(int newMode) {
+            switch (newMode) {
+            case SEARCHABLES_PASSTHROUGH:
+            case SEARCHABLES_MOCK_ZERO:
+                mSearchablesMode = newMode;
+                break;
+                
+            default:
+                throw new UnsupportedOperationException();       
+            }
+        }
+        
+        /**
+         * Find activities that support a given intent.
+         * 
+         * Retrieve all activities that can be performed for the given intent.
+         * 
+         * @param intent The desired intent as per resolveActivity().
+         * @param flags Additional option flags.  The most important is
+         *                    MATCH_DEFAULT_ONLY, to limit the resolution to only
+         *                    those activities that support the CATEGORY_DEFAULT.
+         * 
+         * @return A List<ResolveInfo> containing one entry for each matching
+         *         Activity. These are ordered from best to worst match -- that
+         *         is, the first item in the list is what is returned by
+         *         resolveActivity().  If there are no matching activities, an empty
+         *         list is returned.
+         */
+        @Override 
+        public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
+            assertNotNull(intent);
+            assertEquals(intent.getAction(), Intent.ACTION_SEARCH);
+            switch (mSearchablesMode) {
+            case SEARCHABLES_PASSTHROUGH:
+                return mRealPackageManager.queryIntentActivities(intent, flags);
+            case SEARCHABLES_MOCK_ZERO:
+                return null;
+            default:
+                throw new UnsupportedOperationException();
+            }
+        }
+        
+        /**
+         * Retrieve an XML file from a package.  This is a low-level API used to
+         * retrieve XML meta data.
+         * 
+         * @param packageName The name of the package that this xml is coming from.
+         * Can not be null.
+         * @param resid The resource identifier of the desired xml.  Can not be 0.
+         * @param appInfo Overall information about <var>packageName</var>.  This
+         * may be null, in which case the application information will be retrieved
+         * for you if needed; if you already have this information around, it can
+         * be much more efficient to supply it here.
+         * 
+         * @return Returns an XmlPullParser allowing you to parse out the XML
+         * data.  Returns null if the xml resource could not be found for any
+         * reason.
+         */
+        @Override 
+        public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) {
+            assertNotNull(packageName);
+            MoreAsserts.assertNotEqual(packageName, "");
+            MoreAsserts.assertNotEqual(resid, 0);
+            switch (mSearchablesMode) {
+            case SEARCHABLES_PASSTHROUGH:
+                return mRealPackageManager.getXml(packageName, resid, appInfo);
+            case SEARCHABLES_MOCK_ZERO:
+            default:
+                throw new UnsupportedOperationException();
+            }
+        }
+        
+        /**
+         * Find a single content provider by its base path name.
+         * 
+         * @param name The name of the provider to find.
+         * @param flags Additional option flags.  Currently should always be 0.
+         * 
+         * @return ContentProviderInfo Information about the provider, if found,
+         *         else null.
+         */
+        @Override 
+        public ProviderInfo resolveContentProvider(String name, int flags) {
+            assertNotNull(name);
+            MoreAsserts.assertNotEqual(name, "");
+            assertEquals(flags, 0);
+            switch (mSearchablesMode) {
+            case SEARCHABLES_PASSTHROUGH:
+                return mRealPackageManager.resolveContentProvider(name, flags);
+            case SEARCHABLES_MOCK_ZERO:
+            default:
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+}
+
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java
index 1ea83c3..e6639d3 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java
@@ -98,7 +98,7 @@
             mMetrics = new DisplayMetrics();
             mMetrics.widthPixels = 200;
             mMetrics.heightPixels = 320;
-            mMetrics.density = 120;
+            mMetrics.density = 1;
         }
 
         void setProperty(properties p, int value) {
@@ -131,7 +131,9 @@
                     mMetrics.heightPixels = value;
                     break;
                 case DENSITY:
-                    mMetrics.density = value;
+                    // this is the ratio from the standard
+
+                    mMetrics.density = (((float)value)/((float)DisplayMetrics.DEFAULT_DENSITY));
                     break;
                 default:
                     assert(false);
@@ -187,18 +189,16 @@
          */
         TotalConfig config = new TotalConfig();
         Resources res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple default");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag default"});
+        checkValue(res, R.configVarying.simple, "simple default");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag default"});
 
         config = new TotalConfig();
         config.setProperty(properties.LANGUAGE, "xx");
         res = config.getResources();
-// got simple xx 32dpi
-//        checkValue(res, R.configVarying.simple, "simple xx");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag xx"});
+        checkValue(res, R.configVarying.simple, "simple xx");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag xx"});
 
         config = new TotalConfig();
         config.setProperty(properties.LANGUAGE, "xx");
@@ -225,116 +225,66 @@
         config = new TotalConfig();
         config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_NOTOUCH);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple notouch");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag notouch"});
-
-        config = new TotalConfig();
-        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_FINGER);
-        res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple finger");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag finger"});
+        checkValue(res, R.configVarying.simple, "simple notouch");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag notouch"});
 
         config = new TotalConfig();
         config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
         res = config.getResources();
-// got simple 32dpi stylus
-//        checkValue(res, R.configVarying.simple, "simple stylus");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag stylus"});
+        checkValue(res, R.configVarying.simple, "simple stylus");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag stylus"});
 
         config = new TotalConfig();
         config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_NOKEYS);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple nokeys");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag nokeys"});
-
-        config = new TotalConfig();
-        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_QWERTY);
-        res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple qwerty");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag qwerty"});
+        checkValue(res, R.configVarying.simple, "simple nokeys");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag nokeys"});
 
         config = new TotalConfig();
         config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple 12key");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag 12key"});
-
-        config = new TotalConfig();
-        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_YES);
-        res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple keyshidden");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag keyshidden"});
+        checkValue(res, R.configVarying.simple, "simple 12key");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 12key"});
 
         config = new TotalConfig();
         config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
         res = config.getResources();
-// got simple 32dpi keysexposed
-//        checkValue(res, R.configVarying.simple, "simple keysexposed");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag keysexposed"});
+        checkValue(res, R.configVarying.simple, "simple keysexposed");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag keysexposed"});
 
         config = new TotalConfig();
         config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_NONAV);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple nonav");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag nonav"});
+        checkValue(res, R.configVarying.simple, "simple nonav");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag nonav"});
 
         config = new TotalConfig();
         config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple dpad");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag dpad"});
-
-        config = new TotalConfig();
-        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_TRACKBALL);
-        res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple trackball");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag trackball"});
+        checkValue(res, R.configVarying.simple, "simple dpad");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag dpad"});
 
         config = new TotalConfig();
         config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_WHEEL);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple wheel");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag wheel"});
-
-        config = new TotalConfig();
-        config.setProperty(properties.HEIGHT, 320);
-        config.setProperty(properties.WIDTH, 200);
-        res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple 320x200");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag 320x200"});
+        checkValue(res, R.configVarying.simple, "simple wheel");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag wheel"});
 
         config = new TotalConfig();
         config.setProperty(properties.HEIGHT, 480);
         config.setProperty(properties.WIDTH, 320);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple 480x320");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag 480x320"});
+        checkValue(res, R.configVarying.simple, "simple 480x320");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 480x320"});
 
         config = new TotalConfig();
         config.setProperty(properties.DENSITY, 240);
@@ -344,36 +294,91 @@
                 R.styleable.TestConfig, new String[]{"bag 240dpi"});
 
         config = new TotalConfig();
-        config.setProperty(properties.DENSITY, 120);
-        res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple 120dpi");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag 120dpi"});
-
-        config = new TotalConfig();
         config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_LANDSCAPE);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple landscape");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag landscape"});
-
-        config = new TotalConfig();
-        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_PORTRAIT);
-        res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple portrait");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag portrait"});
+        checkValue(res, R.configVarying.simple, "simple landscape");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag landscape"});
 
         config = new TotalConfig();
         config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
         res = config.getResources();
-// got simple square 32dpi
-//        checkValue(res, R.configVarying.simple, "simple square");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag square"});
+        checkValue(res, R.configVarying.simple, "simple square");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag square"});
+    }
+
+    @MediumTest
+    public void testDensity() throws Exception {
+        // have 32, 240 and the default 160 content.
+        // rule is that closest wins, with down scaling (larger content)
+        // being twice as nice as upscaling.
+        // transition at H/2 * (-1 +/- sqrt(1+8L/H))
+        // SO, X < 49 goes to 32
+        // 49 >= X < 182 goes to 160
+        // X >= 182 goes to 240
+        TotalConfig config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 2);
+        Resources res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 32dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 32dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 32);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 32dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 32dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 48);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 32dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 32dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 49);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple default");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag default"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 150);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple default");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag default"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 181);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple default");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag default"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 182);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 240dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 240dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 239);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 240dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 240dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 490);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 240dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 240dpi"});
     }
 
 // TODO - add tests for special cases - ie, other key params seem ignored if 
@@ -407,10 +412,9 @@
         config = new TotalConfig();
         config.setProperty(properties.MNC, 333);
         res = config.getResources();
-// got simple 24dpi
-//        checkValue(res, R.configVarying.simple, "simple default");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag default"});
+        checkValue(res, R.configVarying.simple, "simple default");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag default"});
     }
 
     @MediumTest
@@ -419,13 +423,31 @@
          * Verify that in cases of ties, the specific ordering is followed
          */
 
-        /* full A + B + C doesn't exist.  Do we get A + C or B + C? 
+        /**
+         * Precidence order: mcc, mnc, locale, orientation, density,
+         * touchscreen, hidden, keyboard, navigation, width-height
+         */
+
+        /**
+         * verify mcc trumps mnc.  Have 110-xx, 220-xx but no 110-220
+         * so with is selected?  Should be mcc110-xx. 
          */
         TotalConfig config = new TotalConfig();
+        config.setProperty(properties.MCC, 110);
+        config.setProperty(properties.MNC, 220);
+        config.setProperty(properties.LANGUAGE, "xx");
+        Resources res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple mcc110 xx");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag mcc110 xx"});
+
+        /* full A + B + C doesn't exist.  Do we get A + C or B + C? 
+         */
+        config = new TotalConfig();
         config.setProperty(properties.MCC, 111);
         config.setProperty(properties.MNC, 222);
         config.setProperty(properties.LANGUAGE, "xx");
-        Resources res = config.getResources();
+        res = config.getResources();
         checkValue(res, R.configVarying.simple, "simple mcc111 mnc222");
         checkValue(res, R.configVarying.bag,
                 R.styleable.TestConfig, new String[]{"bag mcc111 mnc222"});
@@ -433,7 +455,8 @@
         config = new TotalConfig();
         config.setProperty(properties.MNC, 222);
         config.setProperty(properties.LANGUAGE, "xx");
-        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
+        config.setProperty(properties.ORIENTATION, 
+                Configuration.ORIENTATION_SQUARE);
         res = config.getResources();
         checkValue(res, R.configVarying.simple, "simple mnc222 xx");
         checkValue(res, R.configVarying.bag,
@@ -441,60 +464,77 @@
 
         config = new TotalConfig();
         config.setProperty(properties.LANGUAGE, "xx");
-        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
+        config.setProperty(properties.ORIENTATION, 
+                Configuration.ORIENTATION_SQUARE);
         config.setProperty(properties.DENSITY, 32);
         res = config.getResources();
-        checkValue(res, R.configVarying.simple, "simple xx 32dpi");
+        checkValue(res, R.configVarying.simple, "simple xx square");
         checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag xx 32dpi"});
+                R.styleable.TestConfig, new String[]{"bag xx square"});
 
         config = new TotalConfig();
-        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
+        config.setProperty(properties.ORIENTATION, 
+                Configuration.ORIENTATION_SQUARE);
         config.setProperty(properties.DENSITY, 32);
-        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
+        config.setProperty(properties.TOUCHSCREEN, 
+                Configuration.TOUCHSCREEN_STYLUS);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple square 32dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag square 32dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 32);
+        config.setProperty(properties.TOUCHSCREEN, 
+                Configuration.TOUCHSCREEN_STYLUS);
+        config.setProperty(properties.KEYBOARDHIDDEN, 
+                Configuration.KEYBOARDHIDDEN_NO);
         res = config.getResources();
         checkValue(res, R.configVarying.simple, "simple 32dpi stylus");
         checkValue(res, R.configVarying.bag,
                 R.styleable.TestConfig, new String[]{"bag 32dpi stylus"});
 
         config = new TotalConfig();
-        config.setProperty(properties.DENSITY, 32);
-        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
-        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
+        config.setProperty(properties.TOUCHSCREEN, 
+                Configuration.TOUCHSCREEN_STYLUS);
+        config.setProperty(properties.KEYBOARDHIDDEN, 
+                Configuration.KEYBOARDHIDDEN_NO);
+        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
         res = config.getResources();
-        checkValue(res, R.configVarying.simple, "simple 32dpi stylus");
+        checkValue(res, R.configVarying.simple, "simple stylus keysexposed");
         checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag 32dpi stylus"});
+                R.styleable.TestConfig, new String[]{"bag stylus keysexposed"});
 
         config = new TotalConfig();
-        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
-        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
+        config.setProperty(properties.KEYBOARDHIDDEN, 
+                Configuration.KEYBOARDHIDDEN_NO);
         config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
+        config.setProperty(properties.NAVIGATION, 
+                Configuration.NAVIGATION_DPAD);
         res = config.getResources();
-// got simple 32dpi stylus
-//        checkValue(res, R.configVarying.simple, "simple stylus 12key");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag stylus 12key"});
-
-        config = new TotalConfig();
-        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
-        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
-        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD);
-        res = config.getResources();
-// got simple 32dpi exposed
-//        checkValue(res, R.configVarying.simple, "simple stylus keysexposed");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag stylus keysexposed"});
+        checkValue(res, R.configVarying.simple, "simple keysexposed 12key");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag keysexposed 12key"});
 
         config = new TotalConfig();
         config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
-        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD);
+        config.setProperty(properties.NAVIGATION, 
+                Configuration.NAVIGATION_DPAD);
         config.setProperty(properties.HEIGHT, 63);
         config.setProperty(properties.WIDTH, 57);
         res = config.getResources();
-// got simple 240dpi
-//        checkValue(res, R.configVarying.simple, "simple 12key dpad");
-//        checkValue(res, R.configVarying.bag,
-//                R.styleable.TestConfig, new String[]{"bag 12key dpad"});
+        checkValue(res, R.configVarying.simple, "simple 12key dpad");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 12key dpad"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.NAVIGATION, 
+                Configuration.NAVIGATION_DPAD);
+        config.setProperty(properties.HEIGHT, 640);
+        config.setProperty(properties.WIDTH, 400);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple dpad");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag dpad"});
     }
 }
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java b/tests/CoreTests/com/android/internal/telephony/AdnRecordTest.java
similarity index 83%
rename from tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java
rename to tests/CoreTests/com/android/internal/telephony/AdnRecordTest.java
index 6cafdf0..8a4a285 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/AdnRecordTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import junit.framework.TestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -32,7 +32,7 @@
         // Typical record
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C07918150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C07918150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("+18056377243", adn.getNumber());
@@ -42,7 +42,7 @@
         // Empty records, empty strings
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
 
         assertEquals("", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -51,7 +51,7 @@
         //
         // Record too short
         // 
-        adn = new AdnRecord(SimUtils.hexStringToBytes( "FF"));
+        adn = new AdnRecord(IccUtils.hexStringToBytes( "FF"));
 
         assertEquals("", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -61,7 +61,7 @@
         // TOA = 0xff ("control string")
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C07FF8150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C07FF8150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("18056377243", adn.getNumber());
@@ -71,7 +71,7 @@
         // TOA = 0x81 (unknown)
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C07818150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C07818150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("18056377243", adn.getNumber());
@@ -81,7 +81,7 @@
         // Number Length is too long
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C0F918150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C0F918150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -91,7 +91,7 @@
         // Number Length is zero (invalid)
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C00918150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C00918150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -101,7 +101,7 @@
         // Number Length is 2, first number byte is FF, TOA is international
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C0291FF50367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C0291FF50367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -111,7 +111,7 @@
         // Number Length is 2, first number digit is valid, TOA is international
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C0291F150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C0291F150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("+1", adn.getNumber());
@@ -121,7 +121,7 @@
         // An extended record
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes(
+                IccUtils.hexStringToBytes(
                         "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
@@ -129,7 +129,7 @@
         assertFalse(adn.isEmpty());
         assertTrue(adn.hasExtendedRecord());
 
-        adn.appendExtRecord(SimUtils.hexStringToBytes("0206092143658709ffffffffff"));
+        adn.appendExtRecord(IccUtils.hexStringToBytes("0206092143658709ffffffffff"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
         assertEquals("+18885551212,12345678901234567890", adn.getNumber());
@@ -139,7 +139,7 @@
         // An extended record with an invalid extension
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes(
+                IccUtils.hexStringToBytes(
                         "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
@@ -147,7 +147,7 @@
         assertFalse(adn.isEmpty());
         assertTrue(adn.hasExtendedRecord());
 
-        adn.appendExtRecord(SimUtils.hexStringToBytes("0106092143658709ffffffffff"));
+        adn.appendExtRecord(IccUtils.hexStringToBytes("0106092143658709ffffffffff"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
         assertEquals("+18885551212,12345678", adn.getNumber());
@@ -157,7 +157,7 @@
         // An extended record with an invalid extension
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes(
+                IccUtils.hexStringToBytes(
                         "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
@@ -165,7 +165,7 @@
         assertFalse(adn.isEmpty());
         assertTrue(adn.hasExtendedRecord());
 
-        adn.appendExtRecord(SimUtils.hexStringToBytes("020B092143658709ffffffffff"));
+        adn.appendExtRecord(IccUtils.hexStringToBytes("020B092143658709ffffffffff"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
         assertEquals("+18885551212,12345678", adn.getNumber());
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
similarity index 97%
rename from tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java
rename to tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
index f36d96b..5df8991 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import junit.framework.TestCase;
 
@@ -216,12 +216,12 @@
 
         byte unpacked[];
 
-        unpacked = SimUtils.hexStringToBytes("566F696365204D61696C");
+        unpacked = IccUtils.hexStringToBytes("566F696365204D61696C");
         assertEquals("Voice Mail",
                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
 
-        assertEquals(SimUtils.bytesToHexString(unpacked),
-                SimUtils.bytesToHexString(
+        assertEquals(IccUtils.bytesToHexString(unpacked),
+                IccUtils.bytesToHexString(
                         GsmAlphabet.stringToGsm8BitPacked("Voice Mail")));
 
         unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
similarity index 92%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java
rename to tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
index 6db230f..5d5d1f9 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.test.suitebuilder.annotation.MediumTest;
 import com.android.internal.telephony.TestPhoneNotifier;
+import com.android.internal.telephony.gsm.SmsMessage;
 import com.android.internal.telephony.test.SimulatedCommands;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.Suppress;
-import android.telephony.gsm.SmsMessage;
 
 import java.util.Iterator;
 
@@ -37,24 +37,24 @@
         Iterator<SmsHeader.Element> elements;
 
         String[] lines = new String[2];
-
-        lines[0] = "+CMT: ,158";
+        
+        lines[0] = "+CMT: ,158";             
         lines[1] = "07914140279510F6440A8111110301003BF56080426101748A8C0B05040B"
                  + "8423F000035502010106276170706C69636174696F6E2F766E642E776170"
                  + "2E6D6D732D6D65737361676500AF848D0185B4848C8298524F347839776F"
                  + "7547514D4141424C3641414141536741415A4B554141414141008D908918"
                  + "802B31363530323438363137392F545950453D504C4D4E008A808E028000"
                  + "88058103093A8083687474703A2F2F36";
-
+             
         sms = SmsMessage.newFromCMT(lines);
         header = sms.getUserDataHeader();
         assertNotNull(header);
         assertNotNull(sms.getUserData());
-
+                    
         elements = header.getElements().iterator();
         assertNotNull(elements);
     }
-
+    
     @MediumTest
     public void testCMT2() throws Exception {
         SmsMessage sms;
@@ -62,7 +62,7 @@
         Iterator<SmsHeader.Element> elements;
 
         String[] lines = new String[2];
-
+        
 
         lines[0] = "+CMT: ,77";
         lines[1] = "07914140279510F6440A8111110301003BF56080426101848A3B0B05040B8423F"
@@ -74,7 +74,7 @@
         System.out.println("header = " + header);
         assertNotNull(header);
         assertNotNull(sms.getUserData());
-
+                    
         elements = header.getElements().iterator();
         assertNotNull(elements);
     }
@@ -89,7 +89,7 @@
                  + "b0986c46abd96eb89c6ec7ebf97ec0a070482c1a8fc8a472c96c3a9fd0a874"
                  + "4aad5aafd8ac76cbed7abfe0b0784c2e9bcfe8b47acd6ebbdff0b87c4eafdb"
                  + "eff8bc7ecfeffbffffffffffffffffffffffffffff";
-       byte[] data = SimUtils.hexStringToBytes(s);
+       byte[] data = IccUtils.hexStringToBytes(s);
 
        sms = SmsMessage.createFromEfRecord(1, data);
        assertNotNull(sms.getMessageBody());
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java b/tests/CoreTests/com/android/internal/telephony/SimPhoneBookTest.java
similarity index 78%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java
rename to tests/CoreTests/com/android/internal/telephony/SimPhoneBookTest.java
index db55bca..609e768 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SimPhoneBookTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.os.ServiceManager;
 import android.test.suitebuilder.annotation.Suppress;
@@ -27,19 +27,19 @@
 public class SimPhoneBookTest extends TestCase {
 
     public void testBasic() throws Exception {
-        ISimPhoneBook simPhoneBook =
-                ISimPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
+        IIccPhoneBook simPhoneBook =
+                IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
         assertNotNull(simPhoneBook);
 
-        int size[] = simPhoneBook.getAdnRecordsSize(SimConstants.EF_ADN);
+        int size[] = simPhoneBook.getAdnRecordsSize(IccConstants.EF_ADN);
         assertNotNull(size);
         assertEquals(3, size.length);
         assertEquals(size[0] * size[2], size[1]);
         assertTrue(size[2] >= 100);
 
-        List<AdnRecord> adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        List<AdnRecord> adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         // do it twice cause the second time shall read from cache only
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         assertNotNull(adnRecordList);
 
         // Test for phone book update
@@ -47,58 +47,58 @@
         AdnRecord originalAdn = null;
         // We need to maintain the state of the SIM before and after the test.
         // Since this test doesn't mock the SIM we try to get a valid ADN record,
-        // for 3 tries and if this fails, we bail out.
+        // for 3 tries and if this fails, we bail out. 
         for (adnIndex = 3 ; adnIndex >= 1; adnIndex--) {
             listIndex = adnIndex - 1; // listIndex is zero based.
             originalAdn = adnRecordList.get(listIndex);
             assertNotNull("Original Adn is Null.", originalAdn);
             assertNotNull("Original Adn alpha tag is null.", originalAdn.getAlphaTag());
             assertNotNull("Original Adn number is null.", originalAdn.getNumber());
-
-            if (originalAdn.getNumber().length() > 0 &&
-                originalAdn.getAlphaTag().length() > 0) {
+            
+            if (originalAdn.getNumber().length() > 0 &&  
+                originalAdn.getAlphaTag().length() > 0) {   
                 break;
             }
         }
         if (adnIndex == 0) return;
-
+        
         AdnRecord emptyAdn = new AdnRecord("", "");
         AdnRecord firstAdn = new AdnRecord("John", "4085550101");
         AdnRecord secondAdn = new AdnRecord("Andy", "6505550102");
         String pin2 = null;
 
         // udpate by index
-        boolean success = simPhoneBook.updateAdnRecordsInEfByIndex(SimConstants.EF_ADN,
+        boolean success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
                 firstAdn.getAlphaTag(), firstAdn.getNumber(), adnIndex, pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
          AdnRecord tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertTrue(firstAdn.isEqual(tmpAdn));
 
         // replace by search
-        success = simPhoneBook.updateAdnRecordsInEfBySearch(SimConstants.EF_ADN,
+        success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
                 firstAdn.getAlphaTag(), firstAdn.getNumber(),
                 secondAdn.getAlphaTag(), secondAdn.getNumber(), pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertFalse(firstAdn.isEqual(tmpAdn));
         assertTrue(secondAdn.isEqual(tmpAdn));
 
         // erase be search
-        success = simPhoneBook.updateAdnRecordsInEfBySearch(SimConstants.EF_ADN,
+        success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
                 secondAdn.getAlphaTag(), secondAdn.getNumber(),
                 emptyAdn.getAlphaTag(), emptyAdn.getNumber(), pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertTrue(tmpAdn.isEmpty());
 
         // restore the orginial adn
-        success = simPhoneBook.updateAdnRecordsInEfByIndex(SimConstants.EF_ADN,
+        success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
                 originalAdn.getAlphaTag(), originalAdn.getNumber(), adnIndex,
                 pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertTrue(originalAdn.isEqual(tmpAdn));
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java b/tests/CoreTests/com/android/internal/telephony/SimSmsTest.java
similarity index 94%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java
rename to tests/CoreTests/com/android/internal/telephony/SimSmsTest.java
index 6ced23d..1609680 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SimSmsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.os.ServiceManager;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -33,7 +33,7 @@
         ISms sms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
         assertNotNull(sms);
 
-        List<SmsRawData> records = sms.getAllMessagesFromSimEf();
+        List<SmsRawData> records = sms.getAllMessagesFromIccEf();
         assertNotNull(records);
         assertTrue(records.size() >= 0);
 
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
similarity index 62%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java
rename to tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
index 3fbc8f5..e733af9 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import com.android.internal.telephony.gsm.SimTlv;
-import com.android.internal.telephony.gsm.SimUtils;
+import com.android.internal.telephony.IccUtils;
 import junit.framework.TestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -33,46 +33,46 @@
          */
 
         // An EF[ICCID] record
-        data = SimUtils.hexStringToBytes("981062400510444868f2");
-        assertEquals("8901260450014484862", SimUtils.bcdToString(data, 0, data.length));
+        data = IccUtils.hexStringToBytes("981062400510444868f2");
+        assertEquals("8901260450014484862", IccUtils.bcdToString(data, 0, data.length));
 
         // skip the first and last bytes
-        assertEquals("0126045001448486", SimUtils.bcdToString(data, 1, data.length - 2));
+        assertEquals("0126045001448486", IccUtils.bcdToString(data, 1, data.length - 2));
 
         // Stops on invalid BCD value
-        data = SimUtils.hexStringToBytes("98F062400510444868f2");
-        assertEquals("890", SimUtils.bcdToString(data, 0, data.length));
+        data = IccUtils.hexStringToBytes("98F062400510444868f2");
+        assertEquals("890", IccUtils.bcdToString(data, 0, data.length));
 
         /*
         * bcdByteToInt()
         */
 
-        assertEquals(98, SimUtils.bcdByteToInt((byte) 0x89));
+        assertEquals(98, IccUtils.bcdByteToInt((byte) 0x89));
 
         // Out of range is treated as 0
-        assertEquals(8, SimUtils.bcdByteToInt((byte) 0x8c));
+        assertEquals(8, IccUtils.bcdByteToInt((byte) 0x8c));
 
         /*
          * adnStringFieldToString()
          */
 
 
-        data = SimUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff");
+        data = IccUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff");
         // Again, skip prepended 0
         // (this is an EF[ADN] record)
-        assertEquals("Voice Mail", SimUtils.adnStringFieldToString(data, 1, data.length - 15));
+        assertEquals("Voice Mail", IccUtils.adnStringFieldToString(data, 1, data.length - 15));
 
-        data = SimUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF");
+        data = IccUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF");
         // (this is from an EF[ADN] record)
-        assertEquals("\u9673\u539A\u5764/M", SimUtils.adnStringFieldToString(data, 0, data.length));
+        assertEquals("\u9673\u539A\u5764/M", IccUtils.adnStringFieldToString(data, 0, data.length));
 
-        data = SimUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF");
+        data = IccUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF");
         // (this is made up to test since I don't have a real one)
-        assertEquals("Vo\u00ECce M\u00E0il", SimUtils.adnStringFieldToString(data, 0, data.length));
+        assertEquals("Vo\u00ECce M\u00E0il", IccUtils.adnStringFieldToString(data, 0, data.length));
 
-        data = SimUtils.hexStringToBytes("820505302D82d32d31");
+        data = IccUtils.hexStringToBytes("820505302D82d32d31");
         // Example from 3GPP TS 11.11 V18.1.3.0 annex B
-        assertEquals("-\u0532\u0583-1", SimUtils.adnStringFieldToString(data, 0, data.length));
+        assertEquals("-\u0532\u0583-1", IccUtils.adnStringFieldToString(data, 0, data.length));
     }
 
 }
diff --git a/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java b/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
index eb2bd23..b4fb324 100644
--- a/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
+++ b/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
@@ -16,13 +16,13 @@
 
 package com.android.internal.telephony;
 
-import com.android.internal.telephony.gsm.AdnRecordTest;
+import com.android.internal.telephony.AdnRecordTest;
 import com.android.internal.telephony.gsm.GSMPhoneTest;
-import com.android.internal.telephony.gsm.GsmAlphabetTest;
-import com.android.internal.telephony.gsm.SMSDispatcherTest;
-import com.android.internal.telephony.gsm.SimPhoneBookTest;
-import com.android.internal.telephony.gsm.SimSmsTest;
-import com.android.internal.telephony.gsm.SimUtilsTest;
+import com.android.internal.telephony.GsmAlphabetTest;
+import com.android.internal.telephony.SMSDispatcherTest;
+import com.android.internal.telephony.SimPhoneBookTest;
+import com.android.internal.telephony.SimSmsTest;
+import com.android.internal.telephony.SimUtilsTest;
 
 import junit.framework.TestSuite;
 
diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
index 663b7a4..6f89fce 100644
--- a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
+++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
@@ -147,4 +147,56 @@
         // now try moving "down" - nothing should happen since there's no longer an adapter
         sendKeys("DPAD_DOWN");
     }
+    
+    /** Test the show/hide behavior of the drop-down. */
+    @MediumTest
+    public void testPopupShow() throws Throwable {
+        AutoCompleteTextViewSimple theActivity = getActivity();
+        final AutoCompleteTextView textView = theActivity.getTextView();
+        final Instrumentation instrumentation = getInstrumentation();
+        
+        // Drop-down should not be showing when no text has been entered
+        assertFalse("isPopupShowing() on start", textView.isPopupShowing());
+        
+        // focus and type
+        textView.requestFocus();
+        instrumentation.waitForIdleSync();
+        sendKeys("A");
+        
+        // Drop-down should now be visible
+        assertTrue("isPopupShowing() after typing", textView.isPopupShowing());
+        
+        // Clear the text
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                textView.setText("");
+            }
+        });
+        instrumentation.waitForIdleSync();
+        
+        // Drop-down should be hidden when text is cleared
+        assertFalse("isPopupShowing() after text cleared", textView.isPopupShowing());
+        
+        // Set the text, without filtering
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                textView.setText("a", false);
+            }
+        });
+        instrumentation.waitForIdleSync();
+        
+        // Drop-down should still be hidden
+        assertFalse("isPopupShowing() after setText(\"a\", false)", textView.isPopupShowing());
+        
+        // Set the text, now with filtering
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                textView.setText("a");
+            }
+        });
+        instrumentation.waitForIdleSync();
+        
+        // Drop-down should show up after setText() with filtering 
+        assertTrue("isPopupShowing() after text set", textView.isPopupShowing());
+    }
 }
diff --git a/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java b/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
index 0368651..fd05fed 100644
--- a/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
+++ b/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
@@ -17,8 +17,7 @@
 package com.android.internal.policy.impl;
 
 import android.content.Context;
-
-import com.android.internal.telephony.SimCard;
+import com.android.internal.telephony.IccCard;
 import android.test.AndroidTestCase;
 import android.view.View;
 import android.view.KeyEvent;
@@ -39,7 +38,7 @@
 
     private static class MockUpdateMonitor extends KeyguardUpdateMonitor {
 
-        public SimCard.State simState = SimCard.State.READY;
+        public IccCard.State simState = IccCard.State.READY;
         public boolean inPortrait = false;
         public boolean keyboardOpen = false;
 
@@ -48,7 +47,7 @@
         }
 
         @Override
-        public SimCard.State getSimState() {
+        public IccCard.State getSimState() {
             return simState;
         }
 
@@ -339,7 +338,7 @@
 
     public void testMenuDoesntGoToUnlockScreenOnWakeWhenPukLocked() {
         // PUK locked
-        mUpdateMonitor.simState = SimCard.State.PUK_REQUIRED;
+        mUpdateMonitor.simState = IccCard.State.PUK_REQUIRED;
 
         // wake by menu
         mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
diff --git a/tests/sketch/Android.mk b/tests/sketch/Android.mk
new file mode 100644
index 0000000..814e370
--- /dev/null
+++ b/tests/sketch/Android.mk
@@ -0,0 +1,8 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := Sketch
+
+include $(BUILD_PACKAGE)
diff --git a/tests/sketch/AndroidManifest.xml b/tests/sketch/AndroidManifest.xml
new file mode 100755
index 0000000..c44b54e
--- /dev/null
+++ b/tests/sketch/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.android.gesture"
+      android:versionCode="1"
+      android:versionName="1.0.0">
+      <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name="com.android.gesture.example.GestureEntryDemo"
+                  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"/>
+    </application>
+</manifest> 
diff --git a/tests/sketch/res/drawable/icon.png b/tests/sketch/res/drawable/icon.png
new file mode 100755
index 0000000..75024841
--- /dev/null
+++ b/tests/sketch/res/drawable/icon.png
Binary files differ
diff --git a/tests/sketch/res/layout/demo.xml b/tests/sketch/res/layout/demo.xml
new file mode 100755
index 0000000..e516229
--- /dev/null
+++ b/tests/sketch/res/layout/demo.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+    <Spinner 
+        android:id="@+id/spinner"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:drawSelectorOnTop="true"
+        android:prompt="@string/recognition_result"/>
+    
+    <com.android.gesture.GesturePad 
+        android:id="@+id/drawingpad"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"/>
+    
+</LinearLayout>
diff --git a/tests/sketch/res/layout/gestureviewer.xml b/tests/sketch/res/layout/gestureviewer.xml
new file mode 100755
index 0000000..5302d34
--- /dev/null
+++ b/tests/sketch/res/layout/gestureviewer.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content">
+    
+    <Spinner 
+        android:id="@+id/spinner"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:drawSelectorOnTop="true"
+        android:prompt="@string/recognition_result"/>
+    
+    <com.android.gesture.GesturePad 
+        android:id="@+id/drawingpad"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"/>
+
+    <LinearLayout 
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content">        
+       <Button 
+          android:id="@+id/previous"
+          android:text="@string/previous"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"/>
+       <Button 
+          android:id="@+id/remove"
+          android:text="@string/remove"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"/>
+       <Button 
+          android:id="@+id/next"
+          android:text="@string/next"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_weight="1"/>
+    </LinearLayout>
+    
+</LinearLayout>
diff --git a/tests/sketch/res/layout/newgesture_dialog.xml b/tests/sketch/res/layout/newgesture_dialog.xml
new file mode 100755
index 0000000..6e45d81
--- /dev/null
+++ b/tests/sketch/res/layout/newgesture_dialog.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+            
+    <EditText
+        android:id="@+id/gesturename_edit"
+        android:layout_height="wrap_content"
+        android:layout_width="fill_parent"
+        android:layout_marginLeft="20dip"
+        android:layout_marginRight="20dip"
+        android:scrollHorizontally="true"
+        android:autoText="false"
+        android:capitalize="none"
+        android:gravity="fill_horizontal"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+        
+</LinearLayout>
diff --git a/tests/sketch/res/values/strings.xml b/tests/sketch/res/values/strings.xml
new file mode 100755
index 0000000..4c6aa20
--- /dev/null
+++ b/tests/sketch/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="app_name">Gesture Demo</string>
+    <string name="recognition_result">Recognition Result</string>
+    <string name="clear">Clear</string>
+    <string name="newgesture">Add</string>
+    <string name="viewgesture">View</string>
+    <string name="newgesture_dialog_ok">OK</string>
+    <string name="newgesture_dialog_cancel">Cancel</string>
+    <string name="newgesture_text_entry">Gesture Name</string>
+    <string name="previous">Previous</string>
+    <string name="remove">Remove</string>
+    <string name="next">Next</string>
+</resources>
diff --git a/tests/sketch/src/com/android/gesture/Gesture.java b/tests/sketch/src/com/android/gesture/Gesture.java
new file mode 100755
index 0000000..29c07ad
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/Gesture.java
@@ -0,0 +1,361 @@
+/*
+ * 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.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.gesture.recognizer.RecognitionUtil;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+/**
+ * A single stroke gesture.
+ */
+
+public class Gesture implements Parcelable {
+
+    private RectF mBBX;
+    private float mLength = 0;
+    private int mColor;
+    private float mWidth;
+    private ArrayList<PointF> mPtsBuffer = new ArrayList<PointF>();
+    private long mTimestamp = 0;
+    private long mID;
+    
+    private static final long systemStartupTime = System.currentTimeMillis();
+    private static int instanceCount = 0; 
+
+    public Gesture() {
+        mID = systemStartupTime + instanceCount++;
+    }
+
+    public void setColor(int c) {
+        mColor = c;
+    }
+    
+    public void setStrokeWidth(float w) {
+        mWidth = w;
+    }
+    
+    public int getColor() {
+        return mColor;
+    }
+    
+    public float getStrokeWidth() {
+        return mWidth;
+    }
+  
+    public ArrayList<PointF> getPoints() {
+        return this.mPtsBuffer;
+    }
+  
+    public int numOfPoints() {
+        return this.mPtsBuffer.size();
+    }
+
+    public void addPoint(float x, float y) {
+        mPtsBuffer.add(new PointF(x, y));
+        if (mBBX == null) {
+            mBBX = new RectF();
+            mBBX.top = y;
+            mBBX.left = x;
+            mBBX.right = x;
+            mBBX.bottom = y;
+            mLength = 0;
+        }
+        else {
+            PointF lst = mPtsBuffer.get(mPtsBuffer.size()-2);
+            mLength += Math.sqrt(Math.pow(x-lst.x, 2)+Math.pow(y-lst.y, 2));
+            mBBX.union(x, y);
+        }
+        mTimestamp = System.currentTimeMillis();
+    }
+
+    /**
+     * @return the length of the gesture
+     */
+    public float getLength() {
+        return this.mLength;
+    }
+  
+    public RectF getBBX() {
+        return mBBX;
+    }
+  
+    public void setID(long id) {
+        mID = id;
+    }
+    
+    public long getID() {
+        return mID;
+    }
+    
+    public long getTimeStamp() {
+        return mTimestamp;
+    }
+    
+    public void setTimestamp(long t) {
+  	    this.mTimestamp = t;
+    }
+    
+    /**
+     * draw the gesture
+     * @param canvas
+     */
+    public void draw(Canvas canvas) {
+        Paint paint = new Paint();
+        paint.setAntiAlias(true);
+        paint.setDither(true);
+        paint.setColor(mColor);
+        paint.setStyle(Paint.Style.STROKE);
+        paint.setStrokeJoin(Paint.Join.ROUND);
+        paint.setStrokeCap(Paint.Cap.ROUND);
+        paint.setStrokeWidth(mWidth);
+        
+        Path path = null;
+        float mX = 0, mY = 0;
+        Iterator<PointF> it = mPtsBuffer.iterator();
+        while (it.hasNext()) {
+          PointF p = it.next();
+          float x = p.x;
+          float y = p.y;
+          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;
+            }
+          }
+        }
+        
+        canvas.drawPath(path, paint);
+    }
+    
+    /**
+     * convert the gesture to a Path
+     * @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 num of points needed
+     * @return the path
+     */
+    public Path toPath(float width, float height, int numSample) {
+        float[] pts = RecognitionUtil.resample(this, numSample);
+        RectF rect = this.getBBX();
+        float scale = height / rect.height();
+        Matrix matrix = new Matrix();
+        matrix.setTranslate(-rect.left, -rect.top);
+        Matrix scalem = new Matrix();
+        scalem.setScale(scale, scale);
+        matrix.postConcat(scalem);
+        Matrix translate = new Matrix();
+        matrix.postConcat(translate);
+        matrix.mapPoints(pts);
+        
+        Path path = null;
+        float mX = 0, mY = 0;
+        for (int i=0; i<pts.length-1; 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 >= 3 || dy >= 3) {
+                path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
+                mX = x;
+                mY = y;
+            }
+          }
+        }
+        return path;
+    }
+  
+    /**
+     * get a bitmap thumbnail of the gesture with a transparent background
+     * @param w
+     * @param h
+     * @param edge
+     * @param numSample
+     * @param foreground
+     * @return
+     */
+    public Bitmap toBitmap(int w, int h, 
+        int edge, int numSample) {
+        RectF bbx = this.getBBX();
+        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Path path = this.toPath(w - 2 * edge, h - 2 * edge, numSample);
+        Canvas c = new Canvas(bitmap);
+        //c.drawColor(background);
+        c.translate(edge, edge);
+        Paint paint = new Paint();
+        paint.setAntiAlias(true);
+        paint.setDither(true);
+        paint.setColor(mColor);
+        paint.setStyle(Paint.Style.STROKE);
+        paint.setStrokeJoin(Paint.Join.ROUND);
+        paint.setStrokeCap(Paint.Cap.ROUND);
+        paint.setStrokeWidth(2);
+        c.drawPath(path, paint);
+        return bitmap;
+    }
+    
+    /**
+     * save the gesture as XML
+     * @param namespace
+     * @param serializer
+     * @throws IOException
+     */
+    public void toXML(String namespace, XmlSerializer serializer) throws IOException {
+        serializer.startTag(namespace, "stroke");
+        serializer.attribute(namespace, "timestamp", Long.toString(mTimestamp));
+        serializer.attribute(namespace, "id", Long.toString(mID));
+        serializer.attribute(namespace, "color", Integer.toString(mColor));
+        serializer.attribute(namespace, "width", Float.toString(mWidth));
+        Iterator it = this.mPtsBuffer.iterator();
+        String pts = "";
+        while (it.hasNext()) {
+        	PointF fp = (PointF)it.next();
+        	if (pts.length() > 0)
+        		pts += ",";
+        	pts += fp.x + "," + fp.y;
+        }
+        serializer.text(pts);
+        serializer.endTag(namespace, "stroke");
+    }
+    
+    
+    public void createFromString(String str) {
+        StringTokenizer st = new StringTokenizer(str, "#");
+        
+        String para = st.nextToken();
+        StringTokenizer innerst = new StringTokenizer(para, ",");
+        this.mBBX = new RectF();
+        this.mBBX.left = Float.parseFloat(innerst.nextToken());
+        this.mBBX.top = Float.parseFloat(innerst.nextToken());
+        this.mBBX.right = Float.parseFloat(innerst.nextToken());
+        this.mBBX.bottom = Float.parseFloat(innerst.nextToken());
+        
+        para = st.nextToken();
+        innerst = new StringTokenizer(para, ",");
+        while (innerst.hasMoreTokens()) {
+          String s = innerst.nextToken().trim();
+          if (s.length()==0)
+            break;
+          float x = Float.parseFloat(s);
+          float y = Float.parseFloat(innerst.nextToken());
+          this.mPtsBuffer.add(new PointF(x, y));
+        }
+  
+        para = st.nextToken();
+        this.mColor = Integer.parseInt(para);
+        
+        para = st.nextToken();
+        this.mWidth = Float.parseFloat(para);
+        
+        para = st.nextToken();
+        this.mLength = Float.parseFloat(para);
+        
+        para = st.nextToken();
+        this.mTimestamp = Long.parseLong(para);
+    }
+    
+    @Override
+    public String toString() {
+        String str = "";
+        
+        str += "#" + this.mBBX.left + "," + this.mBBX.top + "," +
+               this.mBBX.right + "," + this.mBBX.bottom;
+        
+        str += "#";
+        Iterator<PointF> it = this.mPtsBuffer.iterator();
+        while (it.hasNext()) {
+          PointF fp = it.next();
+          str += fp.x + "," + fp.y + ","; 
+        }
+
+        str += "#";
+        str += this.mColor;
+        
+        str += "#";
+        str += this.mWidth;
+        
+        str += "#";
+        str += this.mLength;
+        
+        str += "#";
+        str += this.mTimestamp;
+  
+        return str;
+    }
+    
+    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+        public Gesture createFromParcel(Parcel in) {
+            String str = in.readString();
+            Gesture stk = new Gesture();
+            stk.createFromString(str);
+            return stk;
+        }
+    
+        public Gesture[] newArray(int size) {
+            return new Gesture[size];
+        }
+    };
+    
+    public static Gesture buildFromArray(byte[] bytes) {
+        String str = new String(bytes);
+        Gesture stk = new Gesture();
+        stk.createFromString(str);
+        return stk;
+    }
+    
+    public static byte[] saveToArray(Gesture stk) {
+        String str = stk.toString();   
+        return str.getBytes();
+    }
+    
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(this.toString());
+    }
+      
+    public int describeContents() {
+        return CONTENTS_FILE_DESCRIPTOR;
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureLib.java b/tests/sketch/src/com/android/gesture/GestureLib.java
new file mode 100755
index 0000000..d0a25f2
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureLib.java
@@ -0,0 +1,280 @@
+/*
+ * 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.Log;
+import android.util.Xml;
+import android.util.Xml.Encoding;
+
+import com.android.gesture.recognizer.Classifier;
+import com.android.gesture.recognizer.Instance;
+import com.android.gesture.recognizer.NearestNeighbor;
+import com.android.gesture.recognizer.Prediction;
+
+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.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+public class GestureLib {
+  
+    private static final String LOGTAG = "GestureLib";
+    private static String namespace = "ink";
+    private final String datapath;
+    private HashMap<String, ArrayList<Gesture>> name2gestures =
+          new HashMap<String, ArrayList<Gesture>>();
+    private Classifier mClassifier;
+
+    public GestureLib(String path) {
+        datapath = path;
+        mClassifier = new NearestNeighbor();
+    }
+    
+    public Classifier getClassifier() {
+        return mClassifier;
+    }
+    
+    /**
+     * get all the labels in the library
+     * @return a set of strings
+     */
+    public Set<String> getLabels() {
+        return name2gestures.keySet();
+    }
+    
+    public ArrayList<Prediction> recognize(Gesture gesture) {
+        Instance instance = Instance.createInstance(gesture, null);
+        return mClassifier.classify(instance);
+    }
+    
+    public void addGesture(String name, Gesture gesture) {
+        Log.v(LOGTAG, "add an example for gesture: " + name);
+        ArrayList<Gesture> gestures = name2gestures.get(name);
+        if (gestures == null) {
+            gestures = new ArrayList<Gesture>();
+            name2gestures.put(name, gestures);
+        }
+        gestures.add(gesture);
+        mClassifier.addInstance(
+            Instance.createInstance(gesture, name));
+    }
+    
+    public void removeGesture(String name, Gesture gesture) {
+      ArrayList<Gesture> gestures = name2gestures.get(name);
+      if (gestures == null) {
+          return;
+      } 
+      
+      gestures.remove(gesture);
+      
+      // if there are no more samples, remove the entry automatically 
+      if (gestures.isEmpty()) {
+          name2gestures.remove(name);
+      }
+      
+      mClassifier.removeInstance(gesture.getID());
+    }
+    
+    public ArrayList<Gesture> getGestures(String label) {
+        ArrayList<Gesture> gestures = name2gestures.get(label);
+        if (gestures != null)
+            return (ArrayList<Gesture>)gestures.clone();
+        else
+            return null;
+    }
+    
+    public void load() {
+        String filename = datapath
+                        + File.separator + "gestures.xml";
+        File f = new File(filename);
+        if (f.exists()) {
+            try {
+                loadInk(filename, null);
+            }
+            catch (SAXException ex) {
+                ex.printStackTrace();
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+    
+    public void save() {
+        try {
+            compactSave();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+    
+    private void compactSave() throws IOException {
+        File f = new File(datapath);
+        if (f.exists() == false) {
+            f.mkdirs();
+        }
+        String filename = datapath + File.separator + "gestures.xml";
+        Log.v(LOGTAG, "save to " + filename);
+        BufferedOutputStream fos = new BufferedOutputStream(
+            new FileOutputStream(filename)); 
+        
+        PrintWriter writer = new PrintWriter(fos);
+        XmlSerializer serializer = Xml.newSerializer();
+        serializer.setOutput(writer);
+        serializer.startDocument(Encoding.ISO_8859_1.name(), null);
+        serializer.startTag(namespace, "gestures");
+        Iterator<String> it = name2gestures.keySet().iterator();
+        while (it.hasNext()) {
+            String key = it.next();
+            ArrayList<Gesture> gestures = name2gestures.get(key);
+            saveGestures(serializer, key, gestures);
+        }
+        
+        serializer.endTag(namespace, "gestures");
+        serializer.endDocument();
+        serializer.flush();
+        writer.close();
+        fos.close();    
+    }
+    
+    private static void saveGestures(XmlSerializer serializer,
+        String name, ArrayList<Gesture> strokes) throws IOException {
+        serializer.startTag(namespace, "gesture");
+        serializer.startTag(namespace, "name");
+        serializer.text(name);
+        serializer.endTag(namespace, "name");
+        Iterator<Gesture> it = strokes.iterator();
+        while (it.hasNext()) {
+          Gesture stk = it.next();
+          stk.toXML(namespace, serializer);
+        }
+        serializer.endTag(namespace, "gesture");
+    }
+  
+    private void loadInk(String filename, String label) throws SAXException, IOException {
+        Log.v(LOGTAG, "load from " + filename);
+        BufferedInputStream in = new BufferedInputStream(
+            new FileInputStream(filename));
+        Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler());
+        in.close();
+    }
+
+    class CompactInkHandler implements ContentHandler {
+        
+        Gesture currentGesture = null;
+        StringBuffer buffer = null;
+        String gestureName;
+        ArrayList<Gesture> gestures;
+        
+        CompactInkHandler() {
+        }
+        
+        // Receive notification of character data.
+        public void characters(char[] ch, int start, int length) {
+            buffer.append(ch, start, length);
+        }
+    
+        //Receive notification of the end of a document.
+        public void   endDocument() {
+        }
+        
+        // Receive notification of the end of an element.
+        public void   endElement(String uri, String localName, String qName) {
+            if (localName.equals("gesture")) {
+              name2gestures.put(gestureName, gestures);
+              gestures = null;
+            } else if (localName.equals("name")) {
+              gestureName = buffer.toString();
+            } else if (localName.equals("stroke")) {
+              StringTokenizer tokenizer = new StringTokenizer(buffer.toString(), ",");
+              while (tokenizer.hasMoreTokens()) {
+                  String str = tokenizer.nextToken();
+                  float x = Float.parseFloat(str);
+                  str = tokenizer.nextToken();
+                  float y = Float.parseFloat(str);
+                  try
+                  {
+                      currentGesture.addPoint(x, y);
+                  }
+                  catch(Exception ex) {
+                      ex.printStackTrace();
+                  }
+              }
+              gestures.add(currentGesture);
+              mClassifier.addInstance(
+                  Instance.createInstance(currentGesture, gestureName));
+              currentGesture = null;
+            }
+        }
+        
+        // End the scope of a prefix-URI mapping.
+        public void   endPrefixMapping(String prefix) {
+        }
+          
+        //Receive notification of ignorable whitespace in element content.
+        public void   ignorableWhitespace(char[] ch, int start, int length) {
+        }
+          
+        //Receive notification of a processing instruction.            
+        public void   processingInstruction(String target, String data) {
+        }
+          
+        // Receive an object for locating the origin of SAX document events.
+        public void   setDocumentLocator(Locator locator) {
+        }
+          
+        // Receive notification of a skipped entity.
+        public void   skippedEntity(String name) {
+        }
+          
+        // Receive notification of the beginning of a document.
+        public void   startDocument() {
+        }
+          
+        // Receive notification of the beginning of an element.
+        public void   startElement(String uri, String localName, String qName, Attributes atts) {
+            if (localName.equals("gesture")) {
+                gestures = new ArrayList<Gesture>();
+            } else if (localName.equals("name")) {
+                buffer = new StringBuffer();
+            } else if (localName.equals("stroke")) {
+                currentGesture = new Gesture();
+                currentGesture.setTimestamp(Long.parseLong(atts.getValue(namespace, "timestamp")));
+                currentGesture.setColor(Integer.parseInt(atts.getValue(namespace, "color")));
+                currentGesture.setStrokeWidth(Float.parseFloat(atts.getValue(namespace, "width")));
+                buffer = new StringBuffer();
+            }
+        }
+          
+        public void   startPrefixMapping(String prefix, String uri) {
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/tests/sketch/src/com/android/gesture/GestureListener.java
old mode 100644
new mode 100755
similarity index 61%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to tests/sketch/src/com/android/gesture/GestureListener.java
index 72790d0..ebb4149
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/tests/sketch/src/com/android/gesture/GestureListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -14,20 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.gesture;
 
-/**
- * {@hide}
- */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+import android.view.MotionEvent;
 
-    }
-
-    SimFileTypeMismatch(String s)
-    {
-        super(s);
-    }
+public interface GestureListener {
+    public void onStartGesture(GesturePad pad, MotionEvent event);
+    public void onGesture(GesturePad pad, MotionEvent event);
+    public void onFinishGesture(GesturePad pad, MotionEvent event);
 }
diff --git a/tests/sketch/src/com/android/gesture/GesturePad.java b/tests/sketch/src/com/android/gesture/GesturePad.java
new file mode 100755
index 0000000..45a09e6
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GesturePad.java
@@ -0,0 +1,371 @@
+/*
+ * 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.gesture;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PointF;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * A view for rendering and processing gestures
+ */
+
+public class GesturePad extends View {
+
+    public static final float TOUCH_TOLERANCE = 4;
+    public static final int default_foreground = Color.argb(255, 255, 255, 0);
+    private int         background = Color.argb(0, 0, 0, 0);
+    private int         foreground = default_foreground;
+    private int         uncertain_foreground = Color.argb(55, 255, 255, 0);
+    private Bitmap      mBitmap;
+    private Canvas      mCanvas;
+    private Path        mPath;
+    private Paint       mBitmapPaint;
+    private Paint       mPaint;
+    private Paint       mDebugPaint;
+    private float       mX, mY;
+    private boolean     mEnableInput = true; 
+    private boolean     mEnableRendering = true;
+    private boolean     mCacheGesture = true;
+    private Gesture       mCurrentGesture = null;
+    ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>();
+
+    private boolean     mShouldFadingOut = true;
+    private boolean     mIsFadingOut = false;
+    private float       mFadingAlpha = 1;
+    
+    private boolean     reconstruct = false;
+    
+    private ArrayList<Path> debug = new ArrayList<Path>();
+    private Handler mHandler = new Handler();
+    
+    private Runnable mFadingOut = new Runnable() {
+      public void run() {
+          mFadingAlpha -= 0.03f;
+          if (mFadingAlpha <= 0) {
+              mIsFadingOut = false;
+              mPath.reset();
+          } else {
+              mHandler.postDelayed(this, 100);
+          }
+          invalidate();
+      }
+   };
+
+    public GesturePad(Context context) {
+        super(context);
+        init();
+    }
+  
+    public GesturePad(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+    
+    public boolean isEnableRendering() {
+        return this.mEnableRendering;
+    }
+    
+    public Gesture getCurrentGesture() {
+        return mCurrentGesture;
+    }
+    
+    public Paint getPaint() {
+        return mPaint;
+    }
+    
+    public void setColor(int c) {
+        this.foreground = c;
+    }
+    
+    public void setFadingAlpha(float f) {
+        mFadingAlpha = f;
+    }
+    
+    public void setCurrentGesture(Gesture stk) {
+        this.mCurrentGesture = stk;
+        reconstruct = true;
+    }
+    
+    private void init() {
+        mDebugPaint = new Paint();
+        mDebugPaint.setColor(Color.WHITE);
+        mDebugPaint.setStrokeWidth(4);
+        mDebugPaint.setAntiAlias(true);
+        mDebugPaint.setStyle(Paint.Style.STROKE);
+        
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setDither(true);
+        mPaint.setColor(foreground);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setStrokeJoin(Paint.Join.ROUND);
+        mPaint.setStrokeCap(Paint.Cap.ROUND);
+        mPaint.setStrokeWidth(12);
+        
+        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
+        mPath = new Path();
+        
+        reconstruct = false;
+    }
+
+    public void cacheGesture(boolean b) {
+        mCacheGesture = b;
+    }
+      
+    public void enableRendering(boolean b) {
+        mEnableRendering = b;
+    }
+  
+    
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        // TODO Auto-generated method stub
+        super.onSizeChanged(w, h, oldw, oldh);
+        
+        if (w <=0 || h <=0)
+            return;
+        
+        int width = w>oldw? w : oldw;
+        int height = h>oldh? h : oldh;
+        Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        mCanvas = new Canvas(newBitmap);
+        
+        if (mBitmap != null) {
+            mCanvas.drawColor(background);
+            mCanvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+            mCanvas.drawPath(mPath, mPaint);
+        }
+        
+        mBitmap = newBitmap;
+    }
+
+    public void addGestureListener(GestureListener l) {
+        this.mGestureListeners.add(l);
+    }
+  
+    public void removeGestureListener(GestureListener l) {
+        this.mGestureListeners.remove(l);
+    }
+  
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.drawColor(background);
+        
+        if (mCacheGesture)
+            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+        
+        if (mIsFadingOut) {
+            int color = foreground;
+            int alpha = (int)(Color.alpha(color) * mFadingAlpha);
+            mPaint.setColor(Color.argb(alpha, 
+                Color.red(color), 
+                Color.green(color), 
+                Color.blue(color)));
+        } else if (mEnableRendering == false) {
+            mPaint.setColor(uncertain_foreground);
+        } else {
+            mPaint.setColor(foreground);
+        }
+        
+        if (reconstruct) {
+            
+            if (this.mCurrentGesture != null) {
+                float xedge = 30;
+                float yedge = 30;
+                float w = this.getWidth() - 2 * xedge;
+                float h = this.getHeight() - 2 * yedge;
+                float sx =  w / this.mCurrentGesture.getBBX().width();
+                float sy = h / mCurrentGesture.getBBX().height();
+                float scale = sx>sy?sy:sx;
+                convertFromStroke(mCurrentGesture);
+                Matrix matrix = new Matrix();
+                matrix.preTranslate(-mCurrentGesture.getBBX().centerX(), -mCurrentGesture.getBBX().centerY());
+                matrix.postScale(scale, scale);
+                matrix.postTranslate(this.getWidth()/2, this.getHeight()/2);
+                this.mPath.transform(matrix);
+            } else {
+                mPath.reset();
+            }
+            
+            reconstruct = false;
+        }
+        
+        canvas.drawPath(mPath, mPaint);
+        
+        Iterator<Path> it = debug.iterator();
+        while (it.hasNext()) {
+            Path path = it.next();
+            canvas.drawPath(path, mDebugPaint);
+        }
+    }
+    
+    public void clearDebugPath() {
+        debug.clear();
+    }
+    
+    public void addDebugPath(Path path) {
+        debug.add(path);
+    }
+    
+    public void addDebugPath(ArrayList<Path> paths) {
+        debug.addAll(paths);
+    }
+    
+    public void clear() {
+        mPath = new Path();
+        this.mCurrentGesture = null;
+        mCanvas.drawColor(background);
+        this.invalidate();
+    }
+    
+    private void convertFromStroke(Gesture stk) {
+        mPath = null;
+        Iterator it = stk.getPoints().iterator();
+        while (it.hasNext()) {
+            PointF p = (PointF) it.next();
+            if (mPath == null) {
+                mPath = new Path();
+                mPath.moveTo(p.x, p.y);
+                mX = p.x;
+                mY = p.y;
+            } else {
+                float dx = Math.abs(p.x - mX);
+                float dy = Math.abs(p.y - mY);
+                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
+                    mPath.quadTo(mX, mY, (p.x + mX)/2, (p.y + mY)/2);
+                    mX = p.x;
+                    mY = p.y;
+                }
+            }
+        }
+        mPath.lineTo(mX, mY);
+    }
+    
+    public void setEnableInput(boolean b) {
+        mEnableInput = b;
+    }
+    
+    public boolean isEnableInput() {
+        return mEnableInput;
+    }
+    
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+      
+        if(mEnableInput == false) 
+            return true;
+        
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                touch_start(event);
+                invalidate();
+                break;
+            case MotionEvent.ACTION_MOVE:
+                touch_move(event);
+                invalidate();
+                break;
+            case MotionEvent.ACTION_UP:
+                touch_up(event);
+                invalidate();
+                break;
+        }
+        return true;
+    }
+    
+    private void touch_start(MotionEvent event) {
+        mIsFadingOut = false;
+        mHandler.removeCallbacks(mFadingOut);
+      
+        float x = event.getX();
+        float y = event.getY();
+
+        mCurrentGesture = new Gesture();
+        mCurrentGesture.addPoint(x, y);
+        
+        mPath.reset();
+        mPath.moveTo(x, y);
+        mX = x;
+        mY = y;
+        
+        Iterator<GestureListener> it = mGestureListeners.iterator();
+        while (it.hasNext()) {
+            it.next().onStartGesture(this, event);
+        }
+    }
+    
+    private void touch_move(MotionEvent event) {
+        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) {
+            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
+            mX = x;
+            mY = y;
+        }
+        
+        mCurrentGesture.addPoint(x, y);
+        
+        Iterator<GestureListener> it = mGestureListeners.iterator();
+        while (it.hasNext()) {
+            it.next().onGesture(this, event);
+        }
+    }
+    
+    public void setFadingOut(boolean b) {
+        mShouldFadingOut = b;
+        mIsFadingOut = false;
+    }
+    
+    public boolean shouldFadingOut() {
+        return mShouldFadingOut;
+    }
+    
+    private void touch_up(MotionEvent event) {
+        mPath.lineTo(mX, mY);
+        
+        if (mCacheGesture)
+            mCanvas.drawPath(mPath, mPaint);
+        
+        // kill this so we don't double draw
+        if (shouldFadingOut()) {
+            mFadingAlpha = 1;
+            mIsFadingOut = true;
+            mHandler.removeCallbacks(mFadingOut);
+            mHandler.postDelayed(mFadingOut, 100);
+        }
+        
+        Iterator<GestureListener> it = mGestureListeners.iterator();
+        while (it.hasNext()) {
+            it.next().onFinishGesture(this, event);
+        }
+    }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java b/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
new file mode 100755
index 0000000..8fee21a
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
@@ -0,0 +1,220 @@
+/*
+ * 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.gesture.example;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+import com.android.gesture.Gesture;
+import com.android.gesture.GestureLib;
+import com.android.gesture.GestureListener;
+import com.android.gesture.GesturePad;
+import com.android.gesture.R;
+import com.android.gesture.recognizer.Prediction;
+
+import java.util.ArrayList;
+
+/**
+ * The demo shows how to construct a gesture-based user interface on Android.
+ */
+
+public class GestureEntryDemo extends Activity {
+  
+    private static final int DIALOG_NEW_ENTRY = 1;
+    private static final int NEW_ID = Menu.FIRST;
+    private static final int VIEW_ID = Menu.FIRST + 1;
+
+    GesturePad  mView;
+    Spinner     mResult;
+    GestureLib  mRecognizer;
+    boolean     mChangedByRecognizer = false;
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.demo);
+        
+        // init the recognizer
+        mRecognizer = new GestureLib("/sdcard/gestureentry");
+        mRecognizer.load();
+        
+        // create the spinner for showing the recognition results
+        // the spinner also allows a user to correct a prediction
+        mResult = (Spinner) findViewById(R.id.spinner);
+        mResult.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                // TODO Auto-generated method stub
+                // correct the recognition result by adding the new example
+                if (mChangedByRecognizer == false) {
+                    mRecognizer.addGesture(parent.getSelectedItem().toString(), 
+                      mView.getCurrentGesture());
+                } else {
+                    mChangedByRecognizer = false;
+                }
+            }
+  
+            public void onNothingSelected(AdapterView<?> parent) {
+              // TODO Auto-generated method stub
+              
+            }
+          
+        });
+        
+        // create the area for drawing a gesture
+        mView = (GesturePad)this.findViewById(R.id.drawingpad);
+        mView.cacheGesture(false);
+        mView.setFadingOut(false);
+        mView.addGestureListener(new GestureListener() {
+            public void onFinishGesture(GesturePad patch, MotionEvent event) {
+                // TODO Auto-generated method stub
+                recognize(patch.getCurrentGesture());
+            }
+            public void onGesture(GesturePad patch, MotionEvent event) {
+              // TODO Auto-generated method stub
+              
+            }
+            public void onStartGesture(GesturePad patch, MotionEvent event) {
+              // TODO Auto-generated method stub
+              
+            }
+        });
+        
+        
+        if (savedInstanceState != null) {
+            mView.setCurrentGesture(
+                (Gesture)savedInstanceState.getParcelable("gesture"));
+        }
+    }
+    
+    @Override
+    protected Dialog onCreateDialog(int id) {
+        // create the dialog for adding a new entry
+        LayoutInflater factory = LayoutInflater.from(this);
+        final View textEntryView =
+             factory.inflate(R.layout.newgesture_dialog, null);
+        return new AlertDialog.Builder(GestureEntryDemo.this)
+            .setTitle(R.string.newgesture_text_entry)
+            .setView(textEntryView)
+            .setPositiveButton(R.string.newgesture_dialog_ok, 
+                new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int whichButton) {
+                    /* User clicked OK so do some stuff */
+                    EditText edittext =
+                      (EditText)((AlertDialog)dialog).findViewById(R.id.gesturename_edit);
+                    String text = edittext.getText().toString().trim();
+                    if (text.length() > 0) {
+                        mRecognizer.addGesture(text, mView.getCurrentGesture());
+                    }
+                }
+            })
+            .setNegativeButton(R.string.newgesture_dialog_cancel,
+                new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int whichButton) {
+                    /* User clicked cancel so do some stuff */
+                }
+            })
+            .create();
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // TODO Auto-generated method stub
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, NEW_ID, 0, R.string.newgesture)
+                .setShortcut('0', 'n')
+                .setIcon(android.R.drawable.ic_menu_add);
+        menu.add(0, VIEW_ID, 0, R.string.viewgesture)
+                .setShortcut('1', 'v')
+                .setIcon(android.R.drawable.ic_menu_view);
+        return true;
+    }
+    
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle all of the possible menu actions.
+        switch (item.getItemId()) {
+            case NEW_ID:
+                // if there has been a gesture on the canvas
+                if (mView.getCurrentGesture() != null) {
+                    showDialog(DIALOG_NEW_ENTRY);
+                }
+                break;
+                
+            case VIEW_ID:
+                startActivityForResult(
+                    new Intent(this, GestureLibViewer.class), VIEW_ID);
+                break;
+        }
+        
+        return super.onOptionsItemSelected(item);
+    }
+    
+    
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        mRecognizer.load();
+        mView.clear();
+    }
+    
+    @Override
+    protected void onPause() {
+        // TODO Auto-generated method stub
+        super.onPause();
+        mRecognizer.save();
+    }
+    
+    
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog) {
+        // TODO Auto-generated method stub
+        super.onPrepareDialog(id, dialog);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        // TODO Auto-generated method stub
+        super.onSaveInstanceState(outState);
+        outState.putParcelable("gesture", mView.getCurrentGesture());
+        mRecognizer.save();
+    }
+
+    public void recognize(Gesture ink) {
+        mChangedByRecognizer = true;
+        ArrayList<Prediction> predictions = mRecognizer.recognize(ink);
+        ArrayAdapter adapter = new ArrayAdapter(this, 
+                    android.R.layout.simple_spinner_item, predictions);
+        adapter.setDropDownViewResource(
+                    android.R.layout.simple_spinner_dropdown_item);
+        mResult.setAdapter(adapter);
+    }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
new file mode 100755
index 0000000..7ae7fc5
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
@@ -0,0 +1,257 @@
+/*
+ * 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.gesture.example;
+
+import android.app.Activity;
+import android.graphics.Matrix;
+import android.graphics.Path;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.Spinner;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+import com.android.gesture.Gesture;
+import com.android.gesture.GestureLib;
+import com.android.gesture.GesturePad;
+import com.android.gesture.R;
+import com.android.gesture.recognizer.Instance;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * GestureLibViewer is for viewing existing gestures and 
+ * removing unwanted gestures.
+ */
+
+public class GestureLibViewer  extends Activity {
+  
+    GesturePad          mView;
+    Spinner             mResult;
+    GestureLib          mRecognizer;
+    ArrayList<Gesture>  mSamples;
+    int                 mCurrentGestureIndex;
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.gestureviewer);
+        
+        // create the area for drawing a glyph
+        mView = (GesturePad)this.findViewById(R.id.drawingpad);
+        mView.cacheGesture(false);
+        mView.setFadingOut(false);
+        mView.setEnableInput(false);
+        
+        // init the recognizer
+        mRecognizer = new GestureLib("/sdcard/gestureentry");
+        mRecognizer.load();
+
+        mResult = (Spinner) findViewById(R.id.spinner);
+        ArrayList<String> list = new ArrayList<String>();
+        list.addAll(mRecognizer.getLabels());
+        Collections.sort(list);
+        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
+                    android.R.layout.simple_spinner_item, 
+                    list);
+        adapter.setDropDownViewResource(
+                    android.R.layout.simple_spinner_dropdown_item);
+        mResult.setAdapter(adapter);
+        mSamples = mRecognizer.getGestures(list.get(0));
+        if (mSamples.isEmpty() == false) {
+            mCurrentGestureIndex = 0;
+            Gesture gesture = mSamples.get(mCurrentGestureIndex);
+            mView.setCurrentGesture(gesture);
+            mView.clearDebugPath();
+            mView.addDebugPath(
+                toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+        }
+        
+        mResult.setOnItemSelectedListener(new OnItemSelectedListener() {
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                // TODO Auto-generated method stub
+                mSamples = mRecognizer.getGestures(
+                    (String)mResult.getSelectedItem());
+                if (mSamples.isEmpty() == false) {
+                    mCurrentGestureIndex = 0;
+                    Gesture gesture = mSamples.get(mCurrentGestureIndex);
+                    mView.setCurrentGesture(gesture);
+                    mView.clearDebugPath();
+                    mView.addDebugPath(
+                        toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+                }
+                mView.invalidate();
+            }
+  
+            public void onNothingSelected(AdapterView<?> parent) {
+              // TODO Auto-generated method stub
+              
+            }
+          
+        });
+        
+        Button remove = (Button)this.findViewById(R.id.remove);
+        remove.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                // TODO Auto-generated method stub
+                if (mSamples.isEmpty())
+                    return;
+                
+                String name = (String)mResult.getSelectedItem();
+                Gesture gesture = mSamples.get(mCurrentGestureIndex);
+                mRecognizer.removeGesture(name, gesture);
+                
+                mSamples = mRecognizer.getGestures(name);
+                
+                if (mSamples == null) {
+                    // delete the entire entry
+                    mCurrentGestureIndex = 0;
+                    ArrayList<String> list = new ArrayList<String>();
+                    list.addAll(mRecognizer.getLabels());
+                    Collections.sort(list);
+                    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
+                                GestureLibViewer.this, 
+                                android.R.layout.simple_spinner_item, 
+                                list);
+                    adapter.setDropDownViewResource(
+                                android.R.layout.simple_spinner_dropdown_item);
+                    mResult.setAdapter(adapter);
+                } else {
+                    if (mCurrentGestureIndex > mSamples.size()-1) {
+                        mCurrentGestureIndex--;
+                    }
+                    gesture = mSamples.get(mCurrentGestureIndex);
+                    mView.setCurrentGesture(gesture);
+                    mView.clearDebugPath();
+                    mView.addDebugPath(
+                        toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+                    mView.invalidate();
+                }
+            }
+        });
+        
+        Button next = (Button)this.findViewById(R.id.next);
+        next.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                // TODO Auto-generated method stub
+                if (mCurrentGestureIndex >= mSamples.size()-1)
+                    return;
+                
+                mCurrentGestureIndex++;
+                Gesture gesture = mSamples.get(mCurrentGestureIndex);
+                mView.setCurrentGesture(gesture);
+                mView.clearDebugPath();
+                mView.addDebugPath(
+                    toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+                mView.invalidate();
+            }
+        });
+
+        Button previous = (Button)this.findViewById(R.id.previous);
+        previous.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                // TODO Auto-generated method stub
+                if (mCurrentGestureIndex >= 1 &&
+                    mSamples.isEmpty() == false) {
+                    mCurrentGestureIndex--;
+                    Gesture gesture = mSamples.get(mCurrentGestureIndex);
+                    mView.setCurrentGesture(gesture);
+                    mView.clearDebugPath();
+                    mView.addDebugPath(
+                        toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+                    mView.invalidate();
+                }
+            }
+        });
+    }
+    
+    public static ArrayList<Path> toPath(Instance instance) {
+        ArrayList<Path> paths = new ArrayList();
+        Path path = null;
+        float minx = 0, miny = 0;
+        float mX = 0, mY = 0;
+        for (int i=0; i<instance.vector.length; i+=2) {
+            float x = instance.vector[i];
+            float y = instance.vector[i+1];
+            if (x < minx)
+                minx = x;
+            if (y < miny)
+                miny = y;
+            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;
+              }
+            }
+        }
+        Matrix matrix = new Matrix();
+        matrix.setTranslate(-minx + 10, -miny + 10);
+        path.transform(matrix);
+        paths.add(path);
+        
+        path = new Path();
+        path.moveTo(instance.vector[0]-5, instance.vector[1]-5);
+        path.lineTo(instance.vector[0]-5, instance.vector[1]+5);
+        path.lineTo(instance.vector[0]+5, instance.vector[1]+5);
+        path.lineTo(instance.vector[0]+5, instance.vector[1]-5);
+        path.close();
+        path.transform(matrix);
+        paths.add(path);
+        
+        return paths;
+    }
+    
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+      // TODO Auto-generated method stub
+      if (keyCode == KeyEvent.KEYCODE_BACK) {
+          mRecognizer.save();
+          this.setResult(RESULT_OK);
+          finish();
+          return true;
+      }
+      else
+        return false;
+    }
+    
+    @Override
+    protected void onPause() {
+        // TODO Auto-generated method stub
+        super.onPause();
+        mRecognizer.save();
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        // TODO Auto-generated method stub
+        super.onSaveInstanceState(outState);
+        mRecognizer.save();
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Classifier.java b/tests/sketch/src/com/android/gesture/recognizer/Classifier.java
new file mode 100755
index 0000000..584e0a5
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/recognizer/Classifier.java
@@ -0,0 +1,42 @@
+/*
+ * 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.gesture.recognizer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * The abstract class of Classifier
+ */
+public abstract class Classifier {
+	
+	HashMap<Long, Instance> mInstances = new HashMap<Long, Instance>();
+	
+	public void addInstance(Instance instance) {
+		mInstances.put(instance.id, instance);
+	}
+	
+	public Instance getInstance(long id) {
+	    return mInstances.get(id);
+	}
+	
+	public void removeInstance(long id) {
+	    mInstances.remove(id);
+	}
+	
+	public abstract ArrayList<Prediction> classify(Instance instance);
+}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Instance.java b/tests/sketch/src/com/android/gesture/recognizer/Instance.java
new file mode 100755
index 0000000..2eaa1c2
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/recognizer/Instance.java
@@ -0,0 +1,78 @@
+/*
+ * 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.gesture.recognizer;
+
+import android.graphics.PointF;
+
+import com.android.gesture.Gesture;
+
+/**
+ * An instance represents a sample if the label is available or a query if
+ * the label is null.
+ */
+public class Instance {
+
+    private final static float[] targetOrientations = {
+        0, 45, 90, 135, 180, -0, -45, -90, -135, -180
+    };
+    
+    // the feature vector
+    public final float[] vector;
+    // the label can be null
+	public final String	label;
+	// the length of the vector
+	public final float length;
+	// the id of the instance
+	public final long id;
+
+	Instance(long d, float[] v, String l) {
+		id = d;
+		vector = v;
+		label = l;
+		float sum = 0;
+		for (int i = 0; i < vector.length; i++) {
+			sum += vector[i] * vector[i];
+		}
+		length = (float)Math.sqrt(sum);
+	}
+	
+    public static Instance createInstance(Gesture gesture, String label) {
+        float[] pts = RecognitionUtil.resample(gesture, 64);
+        PointF center = RecognitionUtil.computeCentroid(pts);
+        float inductiveOrientation = (float)Math.atan2(pts[1] - center.y, 
+                pts[0] - center.x);
+        inductiveOrientation *= 180 / Math.PI;
+        
+        float minDeviation = Float.MAX_VALUE;
+        for (int i=0; i<targetOrientations.length; i++) {
+            float delta = targetOrientations[i] - inductiveOrientation;
+            if (Math.abs(delta) < Math.abs(minDeviation)) {
+                minDeviation = delta;
+            }
+        }
+        
+        android.graphics.Matrix m = new android.graphics.Matrix();
+        m.setTranslate(-center.x, -center.y);
+        android.graphics.Matrix rotation = new android.graphics.Matrix();
+        rotation.setRotate(minDeviation);
+        m.postConcat(rotation);
+        m.mapPoints(pts);
+
+        return new Instance(gesture.getID(), pts, label);
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java b/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java
new file mode 100755
index 0000000..cb8a9d3
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java
@@ -0,0 +1,90 @@
+/*
+ * 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.gesture.recognizer;
+
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+public class NearestNeighbor extends Classifier {
+  
+    private static final String LOGTAG = "NearestNeighbor";
+    private static final double variance = 0.25; // std = 0.5
+    
+    public ArrayList<Prediction> classify(Instance instance) {
+    
+        ArrayList<Prediction> list = new ArrayList<Prediction>();
+        Iterator<Instance> it = mInstances.values().iterator();
+        Log.v(LOGTAG, mInstances.size() + " instances found");
+        TreeMap<String, Double> label2score = new TreeMap<String, Double>();
+        while (it.hasNext()) {
+            Instance sample = it.next();
+            double dis = RecognitionUtil.cosineDistance(sample, instance);
+            double weight = Math.exp(-dis*dis/(2 * variance));
+            Log.v(LOGTAG, sample.label + " = " + dis + " weight = " + weight);
+            Double score = label2score.get(sample.label);
+            if (score == null) {
+                score = weight;
+            }
+            else {
+                score += weight;
+            }
+            label2score.put(sample.label, score);
+        }
+        
+        double sum = 0;
+        Iterator it2 = label2score.keySet().iterator();
+        while (it2.hasNext()) {
+            String name = (String)it2.next();
+            double score = label2score.get(name);
+            sum += score;
+            list.add(new Prediction(name, score));
+        }
+        
+        it2 = list.iterator();
+        while (it2.hasNext()) {
+            Prediction name = (Prediction)it2.next();
+            name.score /= sum;
+        }
+    
+        
+        Collections.sort(list, new Comparator<Prediction>() {
+            public int compare(Prediction object1, Prediction object2) {
+                // TODO Auto-generated method stub
+                double score1 = object1.score;
+                double score2 = object2.score;
+                if (score1 > score2)
+                    return -1;
+                else if (score1 < score2)
+                    return 1;
+                else
+                    return 0;
+            }
+        });
+        
+        it2 = list.iterator();
+        while (it2.hasNext()) {
+            Prediction name = (Prediction)it2.next();
+            Log.v(LOGTAG, "prediction [" + name.label + " = " + name.score + "]");
+        }
+        
+        return list;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
old mode 100644
new mode 100755
similarity index 60%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to tests/sketch/src/com/android/gesture/recognizer/Prediction.java
index 72790d0..c318754
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -14,20 +14,23 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.gesture.recognizer;
 
 /**
- * {@hide}
+ * 
+ * A recognition result that includes the label and its score
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
-
-    }
-
-    SimFileTypeMismatch(String s)
-    {
-        super(s);
-    }
+public class Prediction {
+	public final String label;
+	public double score;
+	
+	public Prediction(String l, double s) {
+		label = l;
+		score = s;
+	}
+	
+	@Override
+    public String toString() {
+	    return label;
+	}
 }
diff --git a/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java b/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java
new file mode 100755
index 0000000..9146b95
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java
@@ -0,0 +1,190 @@
+/*
+ * 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.recognizer;
+
+import android.graphics.PointF;
+
+import com.android.gesture.Gesture;
+
+import java.util.Iterator;
+
+/**
+ * 
+ * Utilities for recognition.
+ */
+
+public class RecognitionUtil {
+  
+    /**
+     * Re-sample a list of points to a given number
+     * @param stk
+     * @param num
+     * @return
+     */
+    public static float[] resample(Gesture gesture, int num) {
+        final float increment = gesture.getLength()/(num - 1);
+        float[] newstk = new float[num*2];
+        float distanceSoFar = 0;
+        Iterator<PointF> it = gesture.getPoints().iterator();
+        PointF lstPoint = it.next();
+        int index = 0;
+        PointF currentPoint = null;
+        try
+        {
+            newstk[index] = lstPoint.x;
+            index++;
+            newstk[index] = lstPoint.y;
+            index++;
+            while (it.hasNext()) {
+                if (currentPoint == null)
+                    currentPoint = it.next();
+                float deltaX = currentPoint.x - lstPoint.x;
+                float deltaY = currentPoint.y - lstPoint.y;
+                float distance = (float)Math.sqrt(deltaX*deltaX+deltaY*deltaY);
+                if (distanceSoFar+distance >= increment) {
+                    float ratio = (increment - distanceSoFar) / distance;
+                    float nx = lstPoint.x + ratio * deltaX;
+                    float ny = lstPoint.y + ratio * deltaY;
+                    newstk[index] = nx;
+                    index++;
+                    newstk[index] = ny;
+                    index++;
+                    lstPoint = new PointF(nx, ny);
+                    distanceSoFar = 0;
+                }
+                else {
+                    lstPoint = currentPoint;
+                    currentPoint = null;
+                    distanceSoFar += distance;
+                }
+            }
+        }
+        catch(Exception ex) {
+            ex.printStackTrace();
+        }
+    
+        for(int i = index; i < newstk.length -1; i+=2) {
+            newstk[i] = lstPoint.x;
+            newstk[i+1] = lstPoint.y;
+        }
+        return newstk;
+    }
+
+    /**
+     * Calculate the centroid of a list of points
+     * @param points
+     * @return the centroid
+     */
+    public static PointF computeCentroid(float[] points) {
+        float centerX = 0;
+        float centerY = 0;
+        for(int i=0; i<points.length; i++)
+        {
+            centerX += points[i];
+            i++;
+            centerY += points[i];
+        }
+        centerX = 2 * centerX/points.length;
+        centerY = 2 * centerY/points.length;
+        return new PointF(centerX, centerY);
+    }
+
+    /**
+     * calculate the variance-covariance matrix, treat each point as a sample
+     * @param points
+     * @return
+     */
+    public static double[][] computeCoVariance(float[] points) {
+        double[][] array = new double[2][2];
+        array[0][0] = 0;
+        array[0][1] = 0;
+        array[1][0] = 0;
+        array[1][1] = 0;
+        for(int i=0; i<points.length; i++)
+        {
+            float x = points[i];
+            i++;
+            float y = points[i];
+            array[0][0] += x * x;
+            array[0][1] += x * y;
+            array[1][0] = array[0][1];
+            array[1][1] += y * y;
+        }
+        array[0][0] /= (points.length/2);
+        array[0][1] /= (points.length/2);
+        array[1][0] /= (points.length/2);
+        array[1][1] /= (points.length/2);
+        
+        return array;
+    }
+    
+
+    public static float computeTotalLength(float[] points) {
+        float sum = 0;
+        for (int i=0; i<points.length - 4; i+=2) {
+            float dx = points[i+2] - points[i];
+            float dy = points[i+3] - points[i+1];
+            sum += Math.sqrt(dx*dx + dy*dy);
+        }
+        return sum;
+    }
+    
+    public static double computeStraightness(float[] points) {
+        float totalLen = computeTotalLength(points);
+        float dx = points[2] - points[0];
+        float dy = points[3] - points[1];
+        return Math.sqrt(dx*dx + dy*dy) / totalLen;
+    }
+
+    public static double computeStraightness(float[] points, float totalLen) {
+        float dx = points[2] - points[0];
+        float dy = points[3] - points[1];
+        return Math.sqrt(dx*dx + dy*dy) / totalLen;
+    }
+
+    public static double averageEuclidDistance(float[] stk1, float[] stk2) {
+        double distance = 0;
+        for (int i = 0; i < stk1.length; i += 2) {
+            distance += PointF.length(stk1[i] - stk2[i], stk1[i+1] - stk2[i+1]);
+        }
+        return distance/stk1.length;
+    }
+    
+    public static double squaredEuclidDistance(float[] stk1, float[] stk2) {
+        double squaredDistance = 0;
+        for (int i = 0; i < stk1.length; i++) {
+            float difference = stk1[i] - stk2[i];
+            squaredDistance += difference * difference;
+        }
+        return squaredDistance/stk1.length;
+    }
+    
+    /**
+     * Calculate the cosine distance between two instances
+     * @param in1
+     * @param in2
+     * @return the angle between 0 and Math.PI
+     */
+    public static double cosineDistance(Instance in1, Instance in2) {
+        float sum = 0;
+        for (int i = 0; i < in1.vector.length; i++) {
+            sum += in1.vector[i] * in2.vector[i];
+        }
+        return Math.acos(sum / (in1.length * in2.length));
+    }
+
+}
diff --git a/tools/layoutlib/bridge/.gitignore b/tools/layoutlib/bridge/.gitignore
new file mode 100644
index 0000000..efa6632
--- /dev/null
+++ b/tools/layoutlib/bridge/.gitignore
@@ -0,0 +1 @@
+bin/*
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index baa3d53..f434e14 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -1145,4 +1145,12 @@
     public Context getApplicationContext() {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public float getApplicationScale() {
+        throw new UnsupportedOperationException();
+    }
 }