Merge change 1957 into donut

* changes:
  Settings: Disable network location service by default, enable GPS instead.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ed5520d..2a47b42 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2069,15 +2069,31 @@
         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
+         * The preferred network mode 7 = Global
+         *                            6 = EvDo only
+         *                            5 = CDMA w/o EvDo
+         *                            4 = CDMA / EvDo auto
+         *                            3 = GSM / WCDMA auto
+         *                            2 = WCDMA only
+         *                            1 = GSM only
+         *                            0 = GSM / WCDMA preferred
          * @hide
          */
         public static final String PREFERRED_NETWORK_MODE =
                 "preferred_network_mode";
 
         /**
+         * The preferred TTY mode     0 = TTy Off, CDMA default
+         *                            1 = TTY Full
+         *                            2 = TTY HCO
+         *                            3 = TTY VCO
+         * @hide
+         */
+        public static final String PREFERRED_TTY_MODE =
+                "preferred_tty_mode";
+
+
+        /**
          * CDMA Cell Broadcast SMS
          *                            0 = CDMA Cell Broadcast SMS disabled
          *                            1 = CDMA Cell Broadcast SMS enabled
diff --git a/core/java/android/webkit/gears/AndroidRadioDataProvider.java b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
index 2d431a8..1384042 100644
--- a/core/java/android/webkit/gears/AndroidRadioDataProvider.java
+++ b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.telephony.CellLocation;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.gsm.GsmCellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
@@ -54,6 +55,7 @@
   public static final class RadioData {
     public int cellId = -1;
     public int locationAreaCode = -1;
+    // TODO: use new SignalStrength instead of asu
     public int signalStrength = -1;
     public int mobileCountryCode = -1;
     public int mobileNetworkCode = -1;
@@ -179,6 +181,7 @@
   private CellLocation cellLocation = null;
 
   /** The last known signal strength */
+  // TODO: use new SignalStrength instead of asu
   private int signalStrength = -1;
 
   /** The last known serviceState */
@@ -207,7 +210,7 @@
     // Register for cell id, signal strength and service state changed
     // notifications.
     telephonyManager.listen(this, PhoneStateListener.LISTEN_CELL_LOCATION
-        | PhoneStateListener.LISTEN_SIGNAL_STRENGTH
+        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
         | PhoneStateListener.LISTEN_SERVICE_STATE);
   }
 
@@ -226,8 +229,9 @@
   }
 
   @Override
-  public void onSignalStrengthChanged(int asu) {
-    signalStrength = asu;
+  public void onSignalStrengthsChanged(SignalStrength ss) {
+    int gsmSignalStrength = ss.getGsmSignalStrength();
+    signalStrength = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
     notifyListeners();
   }
 
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index e1ff2a5..ce32754 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -18,6 +18,8 @@
 
 import com.android.internal.os.BatteryStatsImpl;
 
+import android.telephony.SignalStrength;
+
 interface IBatteryStats {
     byte[] getStatistics();
     void noteStartWakelock(int uid, String name, int type);
@@ -33,7 +35,7 @@
     void noteUserActivity(int uid, int event);
     void notePhoneOn();
     void notePhoneOff();
-    void notePhoneSignalStrength(int asu);
+    void notePhoneSignalStrength(in SignalStrength signalStrength);
     void notePhoneDataConnectionState(int dataType, boolean hasData);
     void noteWifiOn(int uid);
     void noteWifiOff(int uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e8356a2..edc9ec9 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -23,6 +23,7 @@
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.SystemClock;
+import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
@@ -982,14 +983,25 @@
         }
     }
     
-    public void notePhoneSignalStrengthLocked(int asu) {
+    public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
         // Bin the strength.
         int bin;
-        if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT;
-        else if (asu >= 8)  bin = SIGNAL_STRENGTH_GOOD;
-        else if (asu >= 4)  bin = SIGNAL_STRENGTH_MODERATE;
-        else bin = SIGNAL_STRENGTH_POOR;
+
+        if (!signalStrength.isGsm()) {
+            int dBm = signalStrength.getCdmaDbm();
+            if (dBm >= -75) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            else if (dBm >= -85) bin = SIGNAL_STRENGTH_GREAT;
+            else if (dBm >= -95)  bin = SIGNAL_STRENGTH_GOOD;
+            else if (dBm >= -100)  bin = SIGNAL_STRENGTH_MODERATE;
+            else bin = SIGNAL_STRENGTH_POOR;
+        } else {
+            int asu = signalStrength.getGsmSignalStrength();
+            if (asu < 0 || asu >= 99) bin = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            else if (asu >= 16) bin = SIGNAL_STRENGTH_GREAT;
+            else if (asu >= 8)  bin = SIGNAL_STRENGTH_GOOD;
+            else if (asu >= 4)  bin = SIGNAL_STRENGTH_MODERATE;
+            else bin = SIGNAL_STRENGTH_POOR;
+        }
         if (mPhoneSignalStrengthBin != bin) {
             if (mPhoneSignalStrengthBin >= 0) {
                 mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this);
diff --git a/core/res/res/drawable/stat_ecb_mode.png b/core/res/res/drawable/stat_ecb_mode.png
new file mode 100644
index 0000000..a948770
--- /dev/null
+++ b/core/res/res/drawable/stat_ecb_mode.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png b/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png
new file mode 100755
index 0000000..11c2eae
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_dormant_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_dormant_evdo.png b/core/res/res/drawable/stat_sys_data_dormant_evdo.png
new file mode 100755
index 0000000..811fcb5
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_dormant_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_0.png b/core/res/res/drawable/stat_sys_roaming_cdma_0.png
new file mode 100755
index 0000000..c61cce7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml b/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml
new file mode 100644
index 0000000..07dc446
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/stat_sys_battery.xml
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="false">
+    <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim0" android:duration="800" />
+    <item android:drawable="@drawable/stat_sys_roaming_cdma_flash_anim1" android:duration="1200" />
+</animation-list>
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png
new file mode 100755
index 0000000..d62502d
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png
new file mode 100755
index 0000000..c61cce7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_0.png b/core/res/res/drawable/stat_sys_signal_cdma_0.png
new file mode 100755
index 0000000..0ef7d53
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_1.png b/core/res/res/drawable/stat_sys_signal_cdma_1.png
new file mode 100755
index 0000000..f4839d4
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_1.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_2.png b/core/res/res/drawable/stat_sys_signal_cdma_2.png
new file mode 100755
index 0000000..e25a99c
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_2.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_3.png b/core/res/res/drawable/stat_sys_signal_cdma_3.png
new file mode 100755
index 0000000..d828d99
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_3.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_cdma_4.png b/core/res/res/drawable/stat_sys_signal_cdma_4.png
new file mode 100755
index 0000000..53a31ea
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_cdma_4.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_0.png b/core/res/res/drawable/stat_sys_signal_evdo_0.png
new file mode 100755
index 0000000..1b8aec7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_1.png b/core/res/res/drawable/stat_sys_signal_evdo_1.png
new file mode 100755
index 0000000..7ce01fd
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_2.png b/core/res/res/drawable/stat_sys_signal_evdo_2.png
new file mode 100755
index 0000000..890cd59
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_3.png b/core/res/res/drawable/stat_sys_signal_evdo_3.png
new file mode 100755
index 0000000..712c640
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_evdo_4.png b/core/res/res/drawable/stat_sys_signal_evdo_4.png
new file mode 100755
index 0000000..f0537dd
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/raw/lattin_lowercase b/core/res/res/raw/lattin_lowercase
new file mode 100644
index 0000000..ea15357
--- /dev/null
+++ b/core/res/res/raw/lattin_lowercase
@@ -0,0 +1,60 @@
+256 32 26
+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 
+-1.0320373 0.44948834 0.5026982 1.262901 0.023728203 0.35666424 -0.3011761 -0.29305357 -1.2141068 0.7408129 0.3580437 -0.57449627 0.089328125 -0.2748898 0.24193475 0.34128588 -0.17308189 -0.026935482 -0.14250056 -0.5399076 -0.5752277 -1.4722083 -0.5954861 -0.22238986 -2.6316617 -0.615307 -0.7596958 -0.9375199 -0.6210034 0.22707939 -0.025550082 -0.12134152 -0.56391954 -1.0288627 -0.2084017 -1.3599188 0.3679564 -0.94063354 -0.27841672 -0.7137886 -1.0174123 -0.26217672 -0.77808744 -0.94122726 0.079729855 -0.8499919 0.33966482 -0.2227484 -0.5293933 -0.18848658 -0.18806252 0.04655085 1.2125677 -0.5123718 -0.63121176 -0.6841088 0.2854664 -0.47106475 -0.2914258 -0.24383987 0.58822995 0.1848862 -0.08414658 -0.84331983 0.28089076 0.8338416 0.64424884 -0.08822638 0.6026292 0.3966598 0.5018676 -1.6556886 -0.030652374 0.06030074 -0.03885972 0.48495716 0.30927324 0.65247893 -0.23975888 0.3126487 0.12552232 -0.40606382 -0.24021025 0.2239085 0.17895736 -0.2752283 -0.07477209 0.36556083 -0.5580003 0.22353698 0.58177936 -0.52982306 -0.24412508 0.6671521 -0.59883493 0.2713756 -0.34448382 -0.5513394 0.1283845 -0.9786675 -0.62606144 -2.0965924 0.06479836 -0.37276036 1.2126547 0.9212107 0.44119748 1.0288627 0.034679867 1.1907843 0.75170547 0.35206679 0.7273997 0.45056993 0.9378007 -1.5369866 -0.17309512 -1.2507765 1.0952296 1.5189886 1.5939811 0.25394422 0.66708034 0.69421405 0.39794734 0.29738182 0.8495444 0.6583927 0.7242627 0.14712924 -0.20420945 -0.32778937 -0.1488928 -1.7449872 -0.47115076 1.4096025 3.3539834 0.93653834 1.889615 0.034595147 0.85133743 0.888768 0.8602395 0.19983679 -0.2646315 0.34296927 0.16271558 -1.0446007 -0.28894347 -1.4071596 -1.1821536 1.761192 0.7683237 0.34883177 1.2127637 0.960367 0.49257267 -0.12317568 0.87162894 -0.10094326 0.083965614 -0.95773655 -1.4323143 -0.17024235 0.94067466 0.5178371 -1.7006843 1.0176337 0.98305815 1.044752 -0.4755929 1.0607079 0.95405406 0.0037732746 0.39355248 -0.6359591 -0.93546396 -0.43886432 -0.26785922 0.40323904 0.37780532 -0.282651 1.0897744 -0.076653205 0.8621501 0.52201897 -0.47145545 -0.08639464 0.24826962 -0.5449552 -0.70446354 -0.35573912 -0.116620034 -0.3555207 -0.87672955 -0.8332148 0.032643896 -1.4711387 -0.07666701 -0.41090423 -1.7450113 -0.7125798 0.588236 1.011962 -0.10906482 -0.049713787 0.21974635 -0.5164017 0.45955366 -0.21865442 0.054675397 -1.643716 0.0869121 0.33518708 0.7350744 -0.35638383 -0.5359705 -1.1251022 0.6354905 0.014285822 0.07969646 -0.01224353 0.3956445 0.41475978 0.21799022 -0.24329978 -0.18884242 -0.61439615 0.22055328 0.57163405 0.5219093 0.43035847 -0.10191071 -0.47637305 0.07277042 0.5151729 0.26946694 -0.7489405 0.40340453 1.9628311 0.1358872 0.23183657 -0.5884934 0.46311405 0.9058562 0.15964781 -0.2011342 0.7970426 0.72013247 -0.6099858 1.3816767 1.332009 0.44028193 0.5621748 0.86960286 1.4065886 0.047132853 
+-0.5876459 -0.49861982 0.10776312 0.21296671 -0.33432215 0.6860717 -1.0144031 -0.34735164 -0.1619369 -0.29697385 0.23474793 -0.03802241 0.6555007 -0.05209993 0.33327565 0.32580897 0.023576869 -0.30506077 -0.5729418 0.2563657 1.1094613 -0.44860962 0.09360653 0.54840297 0.4260575 -0.6992373 -0.20520735 0.71440935 -0.9723347 0.8040045 0.63410026 0.58063257 0.0136224255 -0.6925302 0.44188362 -0.7033653 0.5922983 0.35525048 -0.53687984 0.1797763 0.9169536 -0.7691884 -0.60692513 0.26153398 -0.069532506 -0.538867 -0.8859806 0.38015127 -0.92498 -0.48258197 -0.88898116 0.19742773 -0.48234966 0.41349337 0.21274965 -0.98993015 -0.47080618 1.105701 -0.08140514 -0.1572882 0.30675626 -0.933662 -0.24383947 -0.42028394 -0.17814463 -1.3032701 0.9004051 -0.87253183 1.115192 0.12463315 1.2909203 -0.0733367 -0.40072724 -1.0145737 -0.39735577 -0.47220743 0.41327307 -0.28179047 -0.043861967 0.055796742 -0.05651231 -0.07193288 0.48533636 1.1923914 0.025903484 0.38037747 1.4659939 0.08858928 -0.2389544 0.2729484 -0.27963135 0.13005349 -1.1585696 -0.7126106 0.36186382 0.33154425 1.2340155 0.7118002 0.7473359 0.006837656 0.09851849 -0.42307237 1.4577137 0.58804166 -0.6891303 -0.40587357 1.0740286 0.03683702 -0.29733622 0.9951917 0.86343867 0.88644445 2.182068 0.5716775 1.0376911 -0.08141223 0.5662745 -0.54189956 -0.6177993 -0.33114722 -0.8763973 0.33553421 -0.82770103 0.2069794 1.5816944 1.1606182 2.2737305 1.127369 1.2190173 2.2908351 -0.16844165 -0.74434006 -1.1939615 -0.7338548 -0.6030772 1.2044704 0.27758908 0.04341341 0.1763783 0.77722347 1.2800475 1.0819324 0.60104007 0.31573844 1.7553719 1.3475811 -0.8430969 -0.92384106 -0.9509633 -0.18090925 -0.62012523 0.32144892 -0.11040283 0.035557035 1.1098006 1.8863741 1.534876 1.8720753 0.91152793 0.22508813 1.0451688 1.1840922 -0.78783786 0.8897153 0.27138832 0.26466617 0.42849094 -2.1830962 -0.043503325 0.35566506 1.2814229 1.0061014 1.4608265 0.22734466 0.19427025 -0.29217315 0.84439886 -0.4345544 -0.10515358 -0.47235605 -0.3699708 -1.1436845 0.55321467 -1.1847504 -0.1958594 0.14161305 -0.049251057 -0.8083699 -0.35083675 -0.04412858 0.1290029 -0.83500767 0.3726739 0.15749925 -0.64612883 0.6160278 0.41822785 0.20624 -0.8318465 1.033156 0.033572674 -1.2793441 0.11257877 -0.4348593 0.17882615 0.12986831 0.57957596 -0.54833245 -0.29726908 -0.35211858 0.104037285 1.2497333 0.41274184 0.43120015 0.5675716 -0.4202907 -0.32985362 -1.142256 -0.4488625 -0.14350273 -0.20391443 -0.5083643 -0.55823666 0.74031174 -0.43515426 0.30245942 0.18587282 0.2055401 0.75232697 0.26275596 -0.07702634 1.410873 0.6440989 -0.90422094 -1.5420893 -0.7410849 0.35951835 -0.89543074 -0.48307157 -0.13803153 0.10946857 -0.8220215 -0.4019354 -1.2127689 -0.43956572 0.9073772 1.0947679 1.035815 1.5543823 -0.025296837 -2.48436 -1.2636491 -0.7632876 -0.6784003 0.24657041 -0.03576962 0.046560217 
+0.16219118 -0.4426603 -0.600031 0.18258785 -0.22529073 -0.65151876 -0.6258459 0.802893 -1.0839835 -0.17222537 -0.65083605 -1.5175898 0.18215714 -0.36140135 -0.49675673 -0.3622017 -0.8149667 -1.6608212 -0.6388111 -1.4454705 -1.1541909 -0.61790717 -0.28906113 -0.35366306 -1.2543796 -0.7093829 -0.98888534 -0.9181567 -0.63943064 0.12450104 -0.09578552 -0.7538275 -0.93561816 -0.5891333 0.15560862 -0.66441643 1.0577961 -0.07506256 0.08393138 0.17169975 1.0148748 -0.06925079 -0.68809485 -0.5896944 -0.1996866 -0.67327726 -0.5468578 -0.37417012 -0.7947043 -0.7525708 0.28118336 0.9260421 0.3027611 0.9822964 0.6237638 0.8722198 0.022905791 -0.037577298 -0.5827326 0.48818904 1.1342663 -0.20865044 -0.04710247 -0.010654767 -0.7887384 0.31152782 0.79465914 -0.0048791366 0.50807536 -0.26687565 -0.9507433 0.4608591 1.0266969 -1.4705683 -0.061186083 -0.21109411 0.99001426 0.78452045 -0.6222921 0.10510122 -0.42242125 0.20869707 0.6328383 0.9256842 0.6576888 2.0937 0.7611171 -0.70748687 0.037744936 -1.4124163 -0.0843527 0.4915949 -0.83560425 -0.38328716 0.15288664 0.30524924 0.57254124 0.41256082 0.23704594 0.69178927 -0.69596875 0.544245 0.06849858 -0.8949961 -0.37929693 -0.9599314 0.23557587 0.07470506 0.36212632 0.8158679 -0.23767526 -0.026285637 -0.0599318 0.59204084 0.12959881 0.1400853 -0.5906369 -0.016372161 -0.8160715 -0.29036832 -1.0383385 0.8936524 0.22328083 1.1923993 0.5806411 0.6526409 0.63405204 -0.19770753 0.23216254 -0.8464065 0.05448277 -0.42121163 0.09593496 -0.3940919 -1.3036078 -0.42130777 -1.5108993 -0.7380616 1.5854365 0.83480376 -0.13829987 -0.16158567 0.37549603 0.10953091 0.39026895 -0.26774323 -1.0740238 -0.3012103 -1.3277439 -0.52309877 -0.15750808 -1.396249 -1.8065764 -0.70957196 -0.2701284 0.80136764 -0.55877876 1.1693957 -0.023915604 0.6109688 0.26837918 0.3847679 -1.0180675 -1.6800753 -0.17039482 -1.9280031 0.14020222 -1.6825341 -0.6809575 0.73719066 1.4824125 1.0057563 0.38886833 0.41541937 0.86456496 0.3738373 0.25312418 -0.49311206 -0.5448705 -0.19806409 0.03642095 -1.2165587 -0.5488742 -1.0539055 -1.383237 0.91086125 2.0450864 0.40860626 -0.4115251 0.77019817 0.41150022 -0.6942789 -0.2623275 -0.3564064 0.71422654 -0.110816024 -0.24622679 -1.6485498 -0.93887424 0.3545291 0.3893998 0.505052 0.81602067 -0.13229635 -0.1546229 0.5264243 0.07832468 -0.8087632 0.3644968 0.4432914 -0.2709118 -0.41903403 0.75777215 -0.29312503 1.0305605 0.68167573 0.84435254 -0.08526038 0.49609768 -0.14810072 -0.20223649 -0.16442187 1.0925809 -0.42481133 -0.20465627 0.4510143 0.1474519 -0.45746815 -0.028668247 0.37599435 2.2844088 1.8621339 1.7369909 1.8354855 1.2473161 0.28396165 -0.08997915 1.6469697 1.3783201 0.91929704 0.4862938 0.34556144 0.44629437 0.2890028 1.2533419 0.09651396 1.3923194 0.60770035 0.976285 0.29779458 1.3238846 0.1512996 -0.051096678 0.64230007 0.2520603 0.20745353 -0.033866037 
+-0.9928002 -0.65029335 -0.32707617 -0.63213104 0.047495916 1.0467823 1.2627105 0.41369182 0.43423036 -0.31745973 -0.10303828 -0.4490784 -1.1289506 -0.12982605 -0.09015896 -0.41713923 -0.9552456 -0.41601163 0.033094466 0.11061575 0.03034314 1.0085478 0.42413545 0.6370122 -0.80927914 1.3770676 0.3047822 -1.092244 -0.63284695 -0.1039884 -0.5155913 -0.2916848 -1.1730976 -1.3406764 -0.4014016 -0.22628841 -0.99272746 -1.2915963 -0.43317 0.6375122 0.14244819 0.3385207 0.1259358 -0.021841656 -0.15069425 -0.14160752 -0.40258723 -0.1944997 -1.4997909 -0.3928863 -0.37465528 -0.53800166 1.0240898 0.52819 1.275291 0.112462245 1.2243528 0.090886466 -1.2444159 -0.829214 -0.56068057 0.08047258 -0.042596154 0.017601306 -0.32116365 -0.112104 0.25719127 0.61710596 0.25098404 -0.18310636 0.19171125 -0.5027974 0.6398731 0.22911249 -0.17384402 -0.40915674 0.6308226 -0.06107232 -1.5945159 -0.26162186 0.48523346 1.2052262 0.6816709 1.3541994 0.5940264 -0.42618665 1.0377761 1.5695388 0.56560785 -2.0908725 -1.3393115 -0.0966352 0.21853672 0.18688229 -1.3811437 -0.7189748 -0.20374478 0.41381744 -0.80065614 0.505686 -0.017379532 0.68715656 -0.1268051 1.3514202 -0.046522304 0.44051644 -1.6699985 -0.18163794 -0.37923735 -0.9181768 -1.5454658 -1.369637 0.1987025 1.4891511 -0.04077638 -0.9291818 0.8886401 0.40813708 0.24677886 0.3432359 0.35186812 -1.1587802 -0.42391884 -0.24800682 -1.2837564 -0.7404945 -2.6592689 -0.2994962 1.1631987 1.9922501 -0.3564703 0.387615 0.38653976 1.7939503 0.24637452 -0.5122606 0.7369326 0.33232284 -2.5826666 -1.6953781 -1.034394 -1.9987204 -1.3348261 -0.97745264 0.7279928 1.3903489 -0.17743021 0.71841097 0.6860481 0.59116197 0.40241712 1.6308252 -0.41697022 -1.7863052 -3.174945 -1.2819895 -2.1388152 -1.9280391 -2.1472805 -1.4430648 -0.3548682 0.2089911 1.3924816 0.9638301 0.46611738 1.244214 -0.080808155 0.98346466 -1.071935 -1.411514 -4.6242075 -3.9676464 -2.158492 -1.143991 -2.724027 -0.3730388 0.5443135 1.1468557 0.7640059 0.29976603 0.013265 -0.2000091 -0.9881151 -0.13313034 -0.85124576 -1.4047194 -3.1513608 -1.59114 -0.48440665 -1.2347834 -1.5911614 -0.66515714 0.19321048 1.1618471 -0.21929866 0.37943915 -0.5288679 -0.8446482 0.4516073 1.559307 -0.7751308 0.1352856 -0.7948278 0.5544108 1.5591183 -0.34893557 -0.58530706 -1.2028453 -0.15346713 0.48009244 0.2714317 -0.21216361 0.79691285 0.18238634 0.033441454 0.9847478 2.6799603 0.04519922 -0.39819828 -0.56808174 -0.5608276 -0.5621788 -0.23777194 -0.4576924 0.09079646 -0.58780473 0.3989908 -1.5877905 0.6298423 0.8041579 -1.615472 -0.04399715 0.645193 0.93147075 -0.9793776 -0.43839702 0.6700141 0.8992372 0.96656436 0.42896184 0.06799507 -0.121551305 0.03643667 0.5107995 1.2391013 0.20313375 -0.8901323 -0.11926519 -0.018502166 1.2909812 0.21382728 -0.2109217 0.3447241 0.09436148 0.07683945 0.33333707 0.0073161237 
+-0.18363933 0.48743215 0.9734924 0.82300645 1.1365234 1.3104441 -1.0992749 -0.43311545 -0.35092866 -0.035903934 -0.6433543 -0.056928437 0.50812507 1.2388171 -0.3643605 -0.008841951 0.43816802 0.4549297 1.7472706 2.4208047 2.3252141 0.9372224 0.58785486 -0.14330845 -0.013962021 -0.17999677 -0.51957333 0.53184605 0.3530506 0.9935447 0.90848666 0.52409446 0.7318021 0.46253845 0.57282305 0.13758732 1.2198166 1.995053 1.7632414 -0.019195529 0.09019049 -0.49321592 -0.35048074 0.7887149 -1.3604357 -0.11380006 -0.2492828 0.48950064 0.94204026 0.89088166 0.62689316 1.2040389 1.5950793 -0.19379832 2.037751 0.55023944 0.10160493 0.5160332 -0.95978534 0.18341489 -0.72510695 0.49078816 -0.68670774 -0.23842214 0.7935416 0.46988228 1.1646838 1.4694536 -0.48905516 0.28097233 0.04768517 -1.4034481 0.76640594 0.061519478 0.2392991 -1.0311254 -0.71537673 -0.6825493 0.20515685 -0.31145504 1.3132821 0.48301062 0.9326164 -0.10253975 -0.550522 0.20858018 -0.64940214 -0.2901015 -0.2658784 0.5320008 -0.89019006 -0.2251651 -1.0973288 -0.48251343 -0.23194161 0.34232897 0.46460086 1.2053684 0.37144804 1.0120065 -0.87289697 -0.19781584 -0.70588326 -0.43817925 -0.24095063 -0.5148169 0.3499117 -0.5846331 -0.34835428 0.70133203 0.07190903 0.6244331 0.7937318 0.8530495 -0.283671 -0.29489642 -0.20501985 -0.15467195 -0.77982306 0.4515451 -0.2610175 -0.40279686 1.1797135 0.4087195 -0.20622212 -1.1451014 0.18354966 -0.0061676195 0.25439322 0.22244005 -0.077419914 0.27753034 -0.06819225 -1.0458517 0.3270537 -0.6740566 -0.07237265 0.10929287 -0.7878886 -0.04869395 -1.0487218 0.42578617 0.33093584 0.3234661 -0.19412623 -0.41848716 -0.0350828 -1.0023264 -0.012715773 0.053522155 -0.2866792 -0.5961487 0.09559097 -0.34835342 -0.09524932 -0.49118337 0.56957 0.42196232 1.2921919 0.8131441 -0.064788125 -1.7430549 -0.62558156 0.97213 -1.3765856 -0.8128312 0.7381559 -0.43193838 0.076701336 0.23626271 1.0206754 0.70695513 1.4030601 0.7459599 1.7041987 0.17755316 -0.85486144 -0.43017942 -0.90989125 -0.8591359 0.06385963 0.8856635 0.58149767 0.2500926 -0.23051058 0.23404106 -0.6145896 0.33282027 0.41465953 0.73938537 0.75265735 0.79452324 0.5817997 -0.57481563 -0.61316687 -0.46185386 -0.35781226 -0.028490746 0.09927312 0.26162767 -0.20475222 0.024335561 0.05881939 -1.2323732 -0.373608 0.13963772 -0.50954455 0.9564329 -0.37169278 -0.8616271 -0.43996695 -0.51271695 0.13569131 0.16073285 0.21087371 -0.7338531 1.3449446 0.5731957 0.320499 0.8503369 -0.17713861 1.3689593 -0.11775142 0.9302247 -0.30367264 -0.31072423 0.2961095 0.4146177 0.5528695 -0.05913442 -1.2418368 0.9448847 -0.30547222 0.06529417 0.413268 1.005242 1.0679544 0.63431513 -0.043095257 0.7806826 -0.31520507 -0.79243994 -1.1498984 0.89927524 0.25603995 -0.44269514 0.34776005 0.6654551 -0.05665421 -0.36200863 -0.62900645 0.010842223 -0.05459169 0.25011125 0.29936904 0.08170453 0.04509235 
+0.009690465 -0.19900858 0.23695074 -0.8527833 0.7951504 0.44841623 -0.6546095 0.9330005 -0.0022787398 0.5766652 -0.2875641 -0.047964577 0.8209985 -0.7325829 -0.2145783 -0.7067027 0.21113175 -0.19916743 1.0258273 0.3416977 -0.20105757 0.09809456 0.45001507 1.1358036 2.2607532 0.95336705 -0.5534635 0.3905341 0.40341926 1.1624514 -1.2155701 -0.625963 0.68108374 -0.98660916 -1.1137917 -0.8787478 1.0133651 -1.1719929 -0.9368648 0.078257546 -1.1073941 0.92955774 -0.05955402 -0.5972838 1.4500264 -0.70287913 -1.183681 0.3724696 0.23585089 -0.3679381 -0.9335203 -1.5331664 -1.5893548 -1.6938283 -1.0725771 -0.49542084 0.031462796 -0.22506425 -0.43936366 -0.044947095 1.0578681 -1.1291034 -0.60197777 -0.8803757 0.4164687 -0.912827 -2.007975 -0.8814496 -0.030242303 -1.3217716 -0.043043572 -1.7046866 -2.070672 -0.58450365 -1.0318846 -1.0900327 0.55438864 -2.3942473 -0.8075006 -0.7958753 -0.13948639 -1.2660352 -1.6287287 -2.5816212 -0.8111587 -1.334735 -0.23634812 -0.5197122 0.06045255 -1.7208738 -0.6113437 0.23798361 0.58538324 -0.37566698 -0.52596563 0.4443061 -0.36761546 -1.0858792 0.21615133 -0.7929561 -0.82223725 -1.3558347 -0.2844464 -0.6494999 0.23790598 -1.4047889 -0.8010049 -1.5404593 -0.9938851 0.30828804 -0.29141438 0.869884 -0.7351973 0.013261275 -0.3938976 0.057773232 -0.89324254 -0.80985504 0.26294863 0.16494235 0.3263755 -1.6506147 -1.2927015 -1.4647912 -0.79118234 0.069916435 0.54857516 0.3988809 0.054044567 0.26490587 -0.46596298 -0.47880006 -0.6702248 -1.1204683 -0.3225188 -0.8432376 0.3759092 0.3213979 0.5734244 0.61776024 -0.8779473 -0.17280982 0.6847301 0.77520096 0.4914681 0.43213725 0.57792497 1.7109307 -0.044153735 0.012072292 -0.39937335 1.5812209 -0.6565631 0.047942918 0.85521436 1.6743236 0.9959537 1.2512233 0.6205493 0.2763869 1.6925939 0.9292307 0.73578787 0.874885 -0.2565264 0.7997615 0.8303917 -0.22887366 -1.1243706 1.8007994 1.2534605 1.6140722 1.9897671 1.5488573 1.893067 -0.20607288 0.49793032 -0.80511737 -0.064834505 1.8497901 -0.16560401 0.94808793 -1.0030471 -1.1840563 -0.84223664 0.5787038 0.7948008 1.1510955 1.3819356 1.7602245 0.9985033 1.3209784 1.2775407 0.31016925 -0.8043905 -0.27551657 0.20225684 0.94588584 0.84695953 0.7840746 0.2983594 0.27549255 0.62448597 -0.004683344 1.5032496 2.1142802 2.1788297 1.1571127 -0.41761285 0.7774305 0.9450229 0.3211568 1.0166515 -0.4663387 0.5738035 -0.018564438 -0.4230945 -0.14041527 0.84957993 -0.18399918 0.4216098 1.5661583 1.4007261 1.6007679 -0.78876674 0.24864393 1.2816767 -0.055437032 0.4390081 1.0154836 -0.5457875 1.003273 -0.56712645 0.106146365 1.2956294 0.8318372 1.7971948 -0.08846512 1.3584287 1.2667234 -0.6410277 -0.5653042 1.2627145 -1.6668738 0.42066106 -0.17088719 0.043896466 -0.32893133 -0.11164542 -0.35801277 1.1171858 -0.18187432 1.9043331 -0.1668761 1.0862815 1.0449603 -0.015431015 
+-0.3056758 0.25940558 0.7462129 0.6350956 0.13632914 -0.6396078 -1.3155322 -1.1040087 -0.33752787 -0.5156164 -1.0465763 -0.6093787 0.40685326 0.6225921 0.2603992 0.5766357 -0.196098 0.12923256 -0.4686261 0.1616566 -0.09910341 -1.0306734 -2.8552198 -1.3635082 -2.2417154 -1.0593598 -2.25758 -1.7030687 1.0617595 -0.49334893 1.1791846 1.4512513 -0.29734978 0.94855225 -0.46216106 -0.84778666 -1.0374062 0.618209 -0.66212726 -0.8803104 -1.7780716 -0.12256134 0.15470175 -0.3464273 0.29547867 0.12165469 1.2727495 0.39479995 -0.7625371 -0.20114647 -1.2006118 -1.1517173 -1.1964978 -1.4148062 -0.46452382 -0.5205421 0.16397645 -0.17937872 0.5736514 -0.52443856 0.69845504 0.4109248 -0.058535002 1.298824 -0.8562251 -0.98890615 -0.031535268 -1.2605784 -1.1179094 -0.18717435 -0.11599437 0.6173255 0.14189507 -1.2777259 -0.04803176 0.39857316 0.8027302 1.2948868 0.52208924 0.2645492 -1.2658685 -0.8756467 -0.45752195 -0.97305286 -1.5142272 -1.969767 0.3244166 0.51413476 -0.85355717 -0.8695191 -0.8742606 -0.5169369 0.2865398 0.7508257 0.79960376 -0.009278044 -0.06197672 -1.7657316 -0.8860684 -0.79440594 -0.24384162 1.7983671 1.3935467 0.474142 1.6855668 1.1444408 -0.9310947 -0.627045 0.10238985 -0.5065145 1.1745216 0.47753122 -1.1510589 -2.0019302 -0.06895789 -0.06828326 0.17690478 1.4180086 0.11025326 0.8729383 1.1315805 0.6586152 -0.21401715 -0.58937716 -1.6295915 0.39105797 -0.4515472 0.46060345 -0.89025563 0.021532096 0.18438768 -0.42909762 -0.1940233 0.6401258 1.670736 1.7877042 1.2986554 0.7997993 0.3297447 -0.5486301 -1.6006788 -0.9164205 -0.26550475 0.12474314 -1.793439 0.11662513 0.06986861 1.0181683 0.08266954 0.2936881 1.6487124 0.1888507 1.9809109 0.78182936 -0.6988833 -0.2592984 -0.3227243 -1.0615262 -0.51933414 -0.7083367 -2.0349166 -0.26193583 -0.86091 0.61426985 2.016055 1.6646006 0.706299 0.4725853 0.41314667 1.5074375 -0.11225649 -1.0601313 -0.59183747 -0.64454836 -0.7303756 -0.2832947 -0.6696172 -0.47461566 0.31139702 -0.08330062 0.14640611 0.8126043 0.52173156 1.4778396 0.12661216 1.2422513 0.4288451 0.5531205 -0.023675961 -0.14848314 0.02674082 -1.5317159 -0.574406 -0.853897 0.77010936 -0.19107993 0.96163034 -0.176591 0.8431422 0.55805457 1.116219 0.644643 0.70558536 -0.6006952 -0.4873829 -0.8154713 -0.7676224 -2.1247323 -0.351832 0.05434874 0.38014942 -0.6010489 0.8107947 0.9159046 0.35858768 0.27016485 -0.3714305 -0.22837786 0.70969987 -1.4209629 -0.19527832 -0.46893156 -1.3820373 -1.2373483 0.6183272 0.4452219 -0.32178953 0.22441939 0.35401177 -1.4855298 -0.44066197 -0.9876982 -1.1699355 1.3939236 0.28869763 -0.39844346 -0.02343711 -0.5377412 -0.7804297 -1.4320343 0.40880522 0.52334285 -0.7213707 1.30111 0.48715797 1.275198 -0.35304925 1.1126703 0.15359367 0.8108517 1.6651682 1.3762898 -0.67302686 -1.4279181 -0.7531475 -0.9934748 0.030440476 
+-0.49390033 -0.31292793 -0.14341341 -1.0862973 -0.3706214 -0.917729 1.2503732 -0.6372911 0.19587392 0.90320843 -0.055828877 0.79066217 0.2321678 0.38464406 0.3701561 -0.37617594 -0.2071116 -0.60444653 0.39481458 0.062365945 -0.99447286 -3.0213697 0.5060912 1.2738554 -0.5925375 -1.5181644 0.09778448 0.2697953 -0.19267328 0.20407742 0.14081734 -0.6437068 0.18408099 -0.6053021 -0.27723262 -0.35750344 -0.44576487 -0.48438174 -0.8467316 2.5810733 0.7299506 0.25862694 -0.308035 0.69809544 1.5615593 -0.0020368996 1.0226985 0.26628277 0.34337828 0.015593567 -0.039158896 0.014295919 0.37394795 -0.61859065 -0.28448352 0.6835833 1.7214603 0.7194885 0.91025305 0.32992917 0.842497 1.210814 0.5381061 -0.6795007 0.7845244 0.9563886 0.34939256 0.102710076 0.13012233 -0.9352901 0.04461366 1.0472523 1.1965214 2.619828 1.3711878 0.5000333 1.1733594 0.64382607 1.0558048 0.25913066 0.04962416 0.08333992 -0.16223904 0.073243335 -0.48345485 -0.28375646 -0.77007437 0.38270566 0.29095805 1.593175 0.08686384 0.24688224 1.3434625 1.3385944 1.7315071 0.9330822 0.8523125 1.2978957 0.8403788 0.5358833 -0.9594337 -1.1224754 -0.40075207 -0.03686821 0.34805986 1.3147393 0.23303686 0.45272878 1.4855192 -1.0431982 0.80949146 0.58750105 1.1060905 1.8840538 -0.16496608 -0.2918124 -0.18584184 -0.7047573 -0.5947921 -0.68926984 -0.31440905 1.4112293 0.66576505 0.19974902 -1.2273028 0.24356414 0.7594955 0.4915143 1.1537526 2.0208123 1.1919701 -0.8120755 -1.118012 -0.8039033 -1.4170723 -0.028158484 -0.7736337 0.77594894 -0.039391574 -0.910505 -0.39012077 -0.048952788 -1.739914 -0.02056478 0.6659631 1.9231532 0.51970273 0.10191216 0.6564516 -0.3903447 0.16854532 -1.8610507 -0.014599784 0.40145606 -0.5709755 -0.017843587 -0.2976934 -1.335705 -1.8860589 -0.43249878 0.24911645 0.45743987 0.71512437 -0.47702938 1.8037142 -2.1761549 0.83217275 -1.0765857 -1.8977274 0.13179322 -0.7804813 -0.41208547 0.1565798 -0.71843237 -2.1171758 -0.007908233 0.15673447 0.5592433 0.037603054 -0.8093797 0.39406008 0.015069545 -0.05856205 -0.10243643 0.9708028 -0.041003425 0.027858358 -0.22732769 0.58554256 -0.6045427 -0.96937007 -0.29179788 0.012901342 0.36039814 0.08429996 0.47153482 1.2750409 -0.2402197 -0.8129474 1.9780393 0.87216604 -0.055099644 -0.26628324 0.4730997 0.85863024 1.052321 -0.36233073 0.21802545 -0.29807645 -0.28770325 0.55728453 -0.8058594 -0.27457213 0.4208236 -0.57195336 -0.5677294 -0.6943857 1.7388229 0.4189239 0.29352695 0.6725497 0.41584912 0.040885866 -0.14428978 -0.019623658 -0.21657433 0.37488264 -0.1699314 -1.6765525 0.70977646 0.18749376 -0.14470248 0.16572474 -0.21837525 0.12511916 0.12277298 1.1531436 0.5886546 1.0130509 0.3537823 -0.29226875 -0.23626257 -0.27147204 -1.4844809 0.19797511 1.1109104 -0.85468996 -0.63044196 0.19030863 -0.7126896 0.5692362 0.53858006 1.1847824 1.1505647 1.1090219 0.6805172 -0.03212272 
+0.007913814 0.84936315 0.63343155 0.48953503 0.8738088 -0.4334685 -0.14249201 0.7003963 0.2841137 -0.27431172 -0.53888065 -0.63378334 -0.5270509 -0.7281488 -0.330037 0.089221716 0.17856309 1.3921409 0.8178016 0.6422645 -0.7251879 -0.4485757 -0.88254017 -0.49093044 0.6509648 -0.90422493 -1.6174037 -1.1409576 -0.036735248 0.5309393 -0.109900385 0.439644 0.63446856 0.410373 -0.90041375 0.062723264 0.33060318 -0.6515516 -0.88883173 -1.1007831 -1.9034175 -1.9359412 -1.3992747 -0.0390991 0.8219576 0.19731815 0.22928527 0.5886194 0.056047425 0.7632858 -0.15625094 1.0565184 0.29244414 1.058512 0.0874988 -0.5009893 -0.9407323 1.1736679 0.17764659 1.1541831 0.22366141 -0.30309552 1.2416975 0.04490746 -0.029892161 0.71131754 0.4629471 0.881109 0.9240799 0.34414068 0.77068406 1.0031897 1.0112455 1.7385699 2.3840353 0.600025 1.4742049 0.7489345 0.6141411 -0.43403733 0.045874253 -0.36916918 0.11485867 -0.3103994 -0.1629431 0.018570876 0.11262723 0.5963563 1.2677126 0.35677487 2.0030365 0.8637655 0.6233087 0.82007927 1.3723211 0.17605686 -0.33698437 -0.27816886 -0.76384985 -0.3091189 0.18557747 -0.14822364 0.18078609 0.13555793 -0.05057325 0.20787439 0.7429149 1.079982 0.8646369 0.5100897 0.45059288 0.4834545 0.57227355 -1.1267767 -0.8606389 0.35562646 0.09668132 0.5387092 1.4743203 0.5479121 0.7318596 -0.06911307 1.2062231 1.72351 1.3589555 0.4896279 1.3801821 1.4991754 0.12980393 -1.6155373 -0.57706094 1.1976542 -0.34902748 0.8213724 0.22475588 0.9260272 -1.2658701 -0.53761715 1.4153898 1.6866657 1.1313872 1.2918012 0.8839073 0.9833983 0.5871293 -0.80093753 -0.62092346 -0.52962863 0.28122553 0.12704062 -1.1872511 0.01250865 -0.5645048 0.33070102 -0.20425741 0.6895397 0.69107914 1.1354426 0.8302134 0.8465539 0.16281489 -0.91153187 -0.24986205 -0.45047536 0.3462041 0.23288007 -0.26083583 0.29257187 0.3154308 0.38851783 0.07364158 0.3200862 0.9290182 1.5276837 1.1016738 0.7413585 0.40556517 0.29947633 -0.37793833 -0.02723981 -0.49036378 -0.15536614 -0.39699948 -1.5078661 -0.30469513 -0.76891875 -0.22209261 0.15049215 2.007306 1.1701336 0.850127 1.2411462 0.1110765 0.08573646 -0.9114614 -0.28927976 -0.35270628 -0.27452227 -1.0484018 -1.8414426 -0.5044207 0.009931684 0.9059458 -0.66148 1.6383811 1.1635393 0.34223107 0.7345541 0.48553008 -0.46975157 -0.09771621 0.2064373 -0.40831178 0.05613608 -1.246291 -0.4791135 0.55562866 0.07447494 0.11813989 0.24122539 -0.14471632 1.1217656 1.1817559 0.41578862 -0.35332623 -0.40995073 0.7061573 0.39384288 -0.70971155 -1.1331282 -0.72592103 -0.23988575 0.41926327 0.9996532 1.0239495 0.06184188 0.40644673 1.127063 2.1828098 1.2488902 -0.3756218 0.11579426 0.38751152 -1.0403051 0.26015887 -0.56934285 -1.308806 -0.93549794 0.34472388 -0.40398064 0.6122497 0.5413968 9.335384E-4 0.43945858 0.5171869 1.150537 -0.03982428 
+-0.04281589 0.17912555 0.11177546 -2.0277448 -1.4380498 -1.069754 -0.05795294 -0.17515501 -0.31269628 0.6461627 0.84028554 -0.11439531 0.8669193 0.4983045 0.38870463 0.5398491 0.40811387 -0.72014225 -0.04690787 -0.70719135 -0.7859748 -0.45783734 -0.28954315 -0.4341929 -0.29108164 0.8021854 0.7936661 1.667713 1.7576307 0.51405644 1.3474803 0.89713615 1.1219721 1.5815213 -0.016587775 -0.70052147 -0.60824466 -1.709584 -1.548762 -0.7955246 0.86813146 -0.9881199 0.8349693 -0.018966123 -0.48228493 -0.88708204 0.48435837 0.88126624 1.1777681 0.7224193 -0.34067193 0.7646806 -1.1690882 -1.1381481 -0.94679874 -1.3690518 0.15539666 0.017479178 -0.38322052 1.2516212 0.57649493 0.89022964 0.22998145 0.33812472 0.21320777 0.5504985 0.24522413 0.2725687 -0.80555964 -1.9190593 0.2469766 -1.0213759 -0.08498454 -0.21052626 -0.2919244 0.71429795 1.3046838 0.73324263 -0.1323501 0.5456764 0.37613457 -0.41410646 -0.13755764 -0.4427845 0.075990655 0.24214323 0.7412368 1.3617707 0.9235044 0.80781204 -0.57678825 -0.59548736 0.5458388 0.32595652 1.1016321 1.5231254 0.5683946 0.43541458 0.27369964 -0.21420872 0.49975133 -0.0069489833 -1.2673442 1.822833 0.6931983 0.77370846 1.1021963 0.6184182 0.09663729 0.05592214 0.3638725 0.94571024 -1.406409 -0.14825377 0.685629 -1.0011239 0.8936033 -0.28291816 -0.9199512 1.1993608 1.6154714 2.0402064 0.8901225 -0.14405484 -0.86432874 0.016678674 0.22340502 0.63215655 -0.72312725 -1.040376 0.88803804 -0.5325414 0.30930457 -0.588593 -0.23722246 -0.009356655 0.4895676 1.4351209 0.5523746 0.16222364 0.45906654 0.17166479 -0.13946642 -0.47695014 0.081548445 -1.5239928 -1.1357517 0.041473724 -2.521038 -0.970511 -2.648776 -0.8162378 0.48254058 0.12578504 0.49402663 0.5303266 0.8569477 -0.078966185 -0.1645747 -0.74802035 0.111712515 -1.1455841 -0.26743686 -0.9942576 -0.4058236 -0.5978243 0.12336995 -0.5690238 0.6451159 1.759227 0.75726664 1.3419937 -0.10753999 -0.4237677 0.42327794 0.87131035 0.075764775 -0.11074565 -1.3602282 -0.48256463 -0.89028 -0.990067 -1.1086117 -0.31196082 0.29917133 1.1849035 0.024827337 0.55807734 -0.015603728 -0.05655328 -0.044300962 -0.29314893 0.65040857 0.28893572 0.10002833 -0.11081047 -0.71215445 -1.162132 -0.6658492 -0.9143596 2.076631 0.80227375 0.3736755 -0.5485538 0.23545386 -0.32170165 0.1741775 0.5634534 0.29092404 0.13463305 -1.2165961 0.040883813 0.23773977 -2.0329037 0.24258971 -0.3299688 0.32317114 -1.0514628 0.6816223 -0.9881947 -1.1202257 0.6430709 0.30352065 -0.45097122 0.31564176 -0.25969523 -1.4737687 -0.51500976 -0.16261342 0.53883386 0.40403664 -0.56394994 1.6383234 1.4451194 1.7861046 0.8720495 0.07647258 0.044152033 -0.3975399 0.35173842 -0.2162056 -0.27966955 0.50301033 -0.7261986 0.2533885 -0.51704 1.6557823 0.41112977 -0.8675332 0.57285154 1.7248181 -1.389647 1.1385014 0.4352173 -0.9512262 -0.4919968 -0.041244067 
+0.2956074 1.1182151 1.5027422 0.9412096 0.883848 0.53453207 -0.6824733 -1.7329184 0.29215556 -1.0664713 -1.3112537 0.05999732 -1.5108445 -0.9944299 -0.19323649 -0.2644091 0.871221 1.903874 1.2490755 0.26457068 0.93972003 -1.033757 -1.6153849 -2.7018385 -1.2955686 -0.65649986 -1.3044168 -1.5319792 -0.53235793 -0.37705743 -1.3550161 -0.006838113 1.1953443 1.0451767 1.1054744 1.1533349 1.1797714 0.8228182 0.23246816 -0.57367295 -0.009902226 0.8475423 0.3522334 1.0115519 0.889261 0.9158824 0.071080334 0.0015903722 0.06889787 0.91588104 0.3603213 -0.32467076 0.3569788 0.41667676 1.5429455 -0.5225634 0.70276475 0.34208706 -0.3256261 -0.9304745 0.51439357 -0.13008387 -0.1721931 -0.040590093 -0.70288885 -1.2309508 -0.021646535 0.40178463 -0.8721161 0.43319193 -0.7072422 0.060357485 -1.0494094 0.6060205 0.565944 2.037301 -0.3067864 -0.3919013 -0.019933827 -0.43662125 0.23015678 -0.8767219 0.021707444 0.53235036 0.5483282 -1.398721 0.56313354 0.7013444 -0.036190342 -0.1335313 -0.62517303 0.9862966 -0.2146825 -0.3448236 0.48634183 0.444159 0.13444614 0.2501853 0.749166 -0.05493052 0.042306706 -1.0368966 -0.852935 0.48688915 0.8865013 0.4484552 0.22393593 0.10352872 0.528977 0.14777796 1.353433 0.21616362 -0.12107844 -0.70821464 -0.06689949 0.33613014 0.8655569 -0.13048056 -0.80289 0.1093693 0.3497498 0.6966498 0.54158914 0.5267601 0.5840491 -0.5716022 0.51759744 0.279121 0.6469175 0.018721526 -0.9165588 -0.33129644 -0.2989738 0.27105504 -0.17189798 0.12768358 -0.07935707 0.5591444 -0.3446024 0.08523511 -0.50029874 -0.21616723 -0.38449705 0.4656421 0.5477522 -0.77020764 -0.48832417 0.9411289 0.7267459 -0.3092057 0.12268404 -0.6119454 0.22670318 0.74831957 0.8180572 0.08070001 1.5556079 -0.25473902 -0.095364235 0.4292261 0.2130632 0.13387963 0.23336355 0.012259077 0.0886926 -0.0803512 -0.013202782 -1.2690494 0.48126858 0.21502548 0.6063719 -1.0522778 0.32099938 -0.31443718 -0.19103038 -0.18454869 1.6542068 1.7123017 1.792968 1.6626309 1.7226545 0.9418823 -0.78036857 -0.6335066 -1.0364059 0.46243918 -1.0561168 0.118185595 -0.37425795 -0.21802837 -0.3570218 0.30949646 2.2207007 2.2542937 1.2781748 0.21232724 0.72611636 0.64181924 0.21380614 -1.04361 -1.3311795 -1.0288168 -0.51371026 0.081282616 -0.25049013 0.6045788 -0.16895561 0.94297117 1.2947154 0.8511928 0.5533415 0.56317186 2.4788494 1.0473653 0.7667373 -1.0910962 -0.41290006 -0.42985398 -0.30916727 0.580241 -0.15176378 0.10277087 -1.3890032 1.2639832 0.33714232 0.44618368 0.64688617 -0.13587433 1.1331939 0.033996906 0.38886765 -1.3915112 -1.4662509 -1.1142306 0.10847518 -0.3262126 0.73301446 0.25512785 0.7657714 0.80122405 -0.24669163 0.09745503 0.40052333 0.064661995 0.8879346 -0.54152143 -0.3087037 -0.84335697 -0.06292779 -0.82209426 -1.2383835 1.1356126 -1.5028735 0.66981196 0.91764796 1.0644772 0.025266688 
+0.054169875 0.50416356 0.3271972 -0.9301833 0.21652839 -0.038687885 -0.5595878 -0.03514637 1.1430416 0.24386612 -0.6416631 0.36628062 0.73662543 0.42405993 0.009165506 0.38370004 0.26518244 0.27496567 1.422118 1.4138584 0.13358647 1.4575922 -0.6403374 0.9911591 1.1611058 2.4581475 2.5973039 1.4532958 2.0551422 -0.126525 -0.22332872 0.04214531 -0.522039 0.9356122 1.2305725 1.3645406 1.0643563 0.76738864 0.76453793 -1.4275064 -0.042251464 0.8838947 1.024991 0.55401087 -0.6874778 0.12775151 -0.82096285 -0.75906426 -0.6071737 -0.3310458 0.63885415 0.013006932 0.39085266 1.1321204 0.7343642 0.25019994 -0.80922425 -2.2393596 -0.6320773 -0.9479633 -1.1885047 0.21669742 0.033343628 -0.8612701 -0.79805523 -0.63473064 0.7463165 0.6222663 2.120868 -0.25640875 -0.12745436 -0.7143044 -0.21490775 -1.1913393 -2.1180048 -0.82045233 -0.863191 -1.1838536 -0.4450233 -0.6583887 0.9758031 -0.6753233 1.2905637 -0.22363187 1.0684047 1.1046281 -0.13292809 0.2180266 -0.17929195 -0.29068938 -0.96840656 -1.9030772 -2.083831 -0.18850215 -1.1153711 -0.7315609 -0.16138475 0.5192054 0.48648322 2.2374945 1.7756654 0.9843091 0.57474726 -0.4133715 -1.1144454 0.15336594 -0.135578 -1.383263 -0.8455869 -0.33583984 -0.57563514 -0.9853469 -0.16544865 1.2119457 2.0316694 -0.23017865 0.067118905 1.0316392 0.72843 0.20260336 -0.42423543 0.8247007 -1.7665085 -1.0417022 -0.10873964 -0.878114 -2.8727272 -0.54285496 0.2235938 0.8905241 0.988788 0.8426971 0.12936299 1.9893659 -0.12740451 -0.49559012 0.20899858 0.3610033 -0.6500899 -0.21658574 -0.3855381 0.88717216 0.15434073 -0.38180098 1.1274192 1.1893336 0.5116243 0.22338742 -0.44897377 0.046196185 -0.031317297 0.19096558 1.1932951 0.78069407 1.4349201 -0.05461625 0.19531511 0.5788153 0.96686244 0.02314253 0.46302533 0.9740254 0.6304072 -0.1100836 -0.44860908 0.0963544 -0.006113122 0.5541759 0.32473308 -0.60847336 -0.24356453 -0.46533066 -0.4147566 -0.5737917 0.19731645 0.17082982 0.7099622 0.5097112 -0.5313502 0.50232077 -1.3257668 -0.5073379 0.7074358 0.5728934 0.27460128 0.0137331225 1.5712615 0.80443066 -0.022655176 -1.018287 -0.10551515 -1.0699911 -0.7019115 0.37888798 0.60749656 -0.1758154 -0.53535265 -1.1967477 -0.1837569 -1.3357344 -0.06390766 -2.4429617 -0.71879315 0.21543084 -2.1522245 0.063485205 0.5525497 -0.32227346 -0.029618682 -0.3618246 -0.8985078 0.54739845 -1.4354612 -0.74116737 -1.9883678 -0.24302344 -1.8093005 -0.22701675 0.19626574 0.50726414 -0.2319044 1.2552956 1.2897125 0.27776304 0.032063443 -0.6175508 0.025687024 0.3555731 -0.2057065 -1.2351775 -1.4488586 -2.2886162 -1.8469691 -2.3295107 -0.44767937 0.1526096 -0.7218935 0.691702 0.6286389 0.31596068 -0.24116607 -0.13040815 0.2881326 -0.7614488 -1.7903879 -1.9337512 -0.05495562 -0.88051957 -1.6157012 -0.69513434 -0.19248225 -0.083010346 0.36231646 0.47790146 -0.4603498 -0.45154113 -0.045486227 
+0.055106346 0.41787943 0.23518866 0.31880543 -0.38273793 -0.2682766 1.0778155 0.4042156 -0.15291376 -0.47785726 0.963963 1.4249189 0.8985458 -0.27776447 0.019896533 -0.5812438 -0.06459716 -0.19112405 -0.62946814 0.54295 0.23195721 0.9534032 0.010409565 1.3205423 0.5932145 0.32752138 1.5774543 1.9195118 -0.030376928 0.13837379 -0.050915137 -1.4262233 -1.0085161 -0.3384635 -0.49806374 -0.9370172 0.4233807 -1.2942129 0.17231672 -0.420346 -0.9430473 0.048888467 1.7149798 1.5791808 0.4654308 -0.02723585 -0.66773456 -0.23915769 -0.1339207 0.33906785 -0.7057244 -0.37358785 0.22308213 1.0703917 -0.0502394 0.53472817 1.1990625 0.34926838 3.0624006 2.2754548 0.67102796 -0.8007039 0.05337989 -0.10574753 0.18577471 -0.5415903 -0.2886772 -0.66623336 0.28378597 1.4872406 -0.103914395 0.9737243 -0.6705913 0.871308 0.8050135 1.3667684 -0.7390036 0.18377334 0.01717305 -0.6959165 -0.4878973 -0.30563766 -0.817897 -0.068907715 -1.0615374 1.2313142 -0.082176894 -1.6712805 -0.99748206 -0.72470546 1.8750712 1.02685 -0.5561742 -0.3798324 -0.41354915 -1.0601358 -0.67894614 -1.2399262 0.5474436 0.43574274 0.8962048 0.29426882 -1.7655823 0.15747674 0.06847538 0.4006593 0.6911222 1.5354555 -1.6488825 0.05324268 -0.33505258 -1.1071844 0.52386737 -0.39782038 -0.8955007 -0.9092952 -1.7802556 -0.29051393 1.1783966 0.6313073 1.3691301 -0.0047625224 1.3301716 0.02845071 -0.9081102 -0.10457654 -0.46546888 0.17082238 -0.43628228 -0.22962645 -0.60518336 0.23394063 0.41293162 0.028935418 0.8656926 -0.095399685 -0.082757115 0.6850507 -0.27329814 -0.45683128 -1.1350302 -1.0679955 -0.3914897 -0.6356563 0.07577153 -0.37803873 -0.33781064 1.0344312 0.32822278 -0.102704495 -0.1184016 0.5760505 0.7050651 -0.054313984 0.627901 0.1575818 -0.30676356 -0.41679442 -0.045143526 -0.5813571 0.35624743 -0.0076093697 0.8080288 0.4550001 0.013023173 0.534028 -1.4493763 1.0299476 1.5145833 0.17779112 -1.5489109 -0.3239421 -0.54179335 0.21931967 0.65108496 0.16176315 -0.05891119 0.20800695 -0.2345356 0.44313958 -0.48574516 -0.34544384 0.09859439 -0.5213528 -0.5245651 0.42955816 -0.23714796 -1.7517997 0.3808775 -0.22120203 0.26605538 0.86619854 0.2691596 0.8758105 -0.29716095 -0.13610734 -0.9696699 1.0143903 0.8557493 -0.6038266 -0.94745547 -0.5068528 0.22818771 0.054011684 -0.06858439 0.4866945 0.1319572 0.8615501 0.7998346 0.6828944 0.63944304 0.43657514 0.11530824 -0.33770826 0.22265 0.10937273 0.28312284 0.7666026 0.4217091 0.16744028 0.3782038 -1.3412882 1.0369437 0.5680506 -0.089417964 -0.20818134 0.32926443 -0.015186675 0.78443193 -0.13253926 -1.0512727 -2.023833 -1.579744 -1.0990884 0.9569256 0.8925721 0.008449898 0.53423846 0.7768666 0.8219754 0.4070805 0.34116495 1.1216707 -0.77431947 0.81390816 0.36757034 -1.9675751 -0.5163851 -0.049916133 -1.5264827 -0.68539524 1.4031739 1.2979785 1.4941788 1.0870292 0.32022315 -0.024885263 
+0.35187542 0.47315323 0.06375262 -0.18984222 -1.2736052 -0.8999239 -0.997694 -0.8987528 -0.47804478 -0.029478105 -0.019916669 -0.4369891 -0.8980929 -0.20077878 -0.10719385 -0.35689318 0.5283762 0.69769657 0.40552226 0.006296066 0.10760209 -0.69400287 -1.461945 -2.1827114 0.29208544 0.18536006 -0.5896288 -0.8280684 0.028656635 -0.09012071 0.59518677 -0.11544407 0.31213024 0.6489615 0.4345046 -0.8844129 0.08879119 0.20575026 0.6370033 -0.13517171 -0.15904762 -0.5102168 0.23000601 0.41792092 -0.02401795 0.3064715 0.1548897 -0.14003162 0.059351787 1.0375793 0.6588556 0.21779591 -0.26621693 0.75663906 -0.19510102 -0.56742275 -1.6483148 -1.6565671 -0.33008495 -0.5709284 -0.51975924 -0.076735534 -0.5761578 -0.15903087 0.07556984 0.061870556 -0.38959303 0.22724189 0.704476 1.4744277 0.017300272 -1.3317512 -0.41149396 -0.9121826 0.12576911 0.11322144 -0.49113247 -0.3358971 -0.28124732 0.11110153 -0.31282726 0.38829947 -0.12805547 0.39773807 -0.09190816 -0.55468875 1.6523923 0.6169196 -0.5511872 -1.1888303 -0.26298913 0.21944387 0.35538852 -1.0735103 -0.17800857 0.56086457 1.3576983 0.6732071 -0.21798316 -1.1658154 -0.32856852 0.117975146 1.4003668 0.6826456 -0.5661123 -1.5624797 -1.051826 -0.9114059 -1.5130702 -0.1632518 0.10499575 -1.5723661 0.5404572 0.005381779 -0.04897828 0.76718336 0.52789724 0.38978118 1.3306682 1.1104105 0.12930803 -1.6451412 -0.11925698 -1.2220145 -1.0614527 -0.21021625 -2.121614 -1.335459 -0.31422734 1.1435674 0.6884448 0.58587325 0.65584224 1.0281944 0.6277289 -0.09816445 -0.53129905 -0.73898196 -0.031157177 -2.344916 -0.63456124 -1.3838433 -1.2652844 -0.5972534 0.4595874 0.26999906 0.7784561 0.7761631 0.5333551 0.2531194 1.0774236 1.2955647 -0.2615722 -0.033877954 -0.7787763 -1.0830741 -0.98037475 -0.64917237 -1.0393287 -0.6947423 -0.58374244 0.56825346 0.9916346 0.7712292 0.024016809 1.6023302 1.4604108 0.7091672 -0.28946757 -0.50924796 -0.08101955 -0.2756575 -0.25395638 -0.6447907 -0.63869923 -0.32539478 1.0040973 0.5129646 0.2051001 0.328489 -0.13469598 0.8387987 0.902618 -0.46215934 -2.160162 0.04436235 0.56642556 -0.09076753 -0.5633889 0.08502111 -0.12905781 -0.15343633 0.8532503 1.2933145 0.89913267 1.733953 0.5114631 1.4074614 0.2260288 -0.31312484 -0.94419056 0.31887692 0.4334419 0.46193427 1.381849 -0.31689852 0.79904824 -0.17585358 0.5734938 0.21458276 0.15711688 0.3290721 0.5831648 -0.7637334 0.57381505 -0.8630074 0.2527237 -0.33452997 1.2638513 0.5631748 -0.10063373 0.40321678 0.4776547 0.4335605 0.31184343 1.0283524 0.27802232 -0.026462551 -0.21133558 0.12532602 -0.62760663 0.055672962 -0.57888365 -0.24829793 0.33881143 1.5783504 0.29588833 1.1031828 0.35389295 -0.26125258 0.48396507 0.27806476 -0.39384633 1.256167 -0.18086882 -0.02372104 0.60454524 0.8846328 -0.3249784 -1.5743482 0.5607076 0.61278063 0.2009954 0.52299225 0.3407996 0.44030198 -0.04769305 
+1.0083325 1.2563883 0.3269431 1.3078287 0.84295434 0.5550376 -1.1927786 0.105989486 1.6804359 0.6015006 0.5888955 0.28701502 0.41692483 -0.20063019 -1.0671381 -0.27044833 0.8014692 0.32928216 -0.57570696 1.7109979 0.54568565 0.51998657 -1.543865 -1.6874943 -0.3404413 0.41200396 0.56588805 0.44190428 0.61120224 0.35038418 -0.46090522 -0.031548217 -0.40125713 -0.10589522 0.5869553 -0.35756853 1.1099161 0.83907634 -0.0050030835 -0.65228534 0.7374727 0.4172007 -0.2481021 1.0330265 1.0469184 0.1658152 1.0818397 0.20922245 0.47621673 0.12936024 0.9671128 0.16733892 0.34958866 0.9867477 -0.14550248 -0.19587873 -0.15191717 1.6282445 0.5961366 1.2804437 0.35263848 -0.42777455 0.6368977 -0.11226808 -0.37632692 -1.0876255 0.18628828 -0.4346012 -0.38747993 -0.8592341 -0.64622927 -0.8564642 0.41310352 1.140438 1.808226 1.9403195 0.93217474 -0.062393554 0.7576254 0.5279841 -0.1278205 -0.42025083 -0.17936504 -1.410886 -0.28456286 0.093892656 -0.22450067 -1.295944 -1.4105871 -0.1896959 0.7412809 0.67439556 0.8382402 1.1183988 1.6613656 0.6632143 0.50252956 -1.2373469 0.03698615 -0.5835882 0.9991381 -0.54000646 -1.0260727 -1.0240809 -1.6143155 -1.2315942 -0.6885135 1.2314854 0.77991295 -0.65210646 0.79229623 0.25512183 0.59785014 -0.28666192 0.3890677 -0.4417693 -0.7320765 -0.042777985 -0.3655988 -0.57088256 -0.11965964 -0.6321418 0.7329079 -1.3911293 -0.011395408 -0.004248459 0.22809032 -0.18939714 0.19686174 -0.47076246 -0.54999363 -0.09355236 0.4728932 -1.1669586 0.4945695 -1.234374 -0.8117787 -0.4626087 -0.40752622 -1.1011096 -0.9894822 -0.20655678 -0.49239063 -0.17434435 -0.69516337 0.43387577 0.25678688 -0.27931455 -0.41186506 -1.3642126 -0.3401552 -0.48386443 -2.7799659 -0.8124723 -0.6928424 -2.5047672 -0.86536664 -1.1230178 -1.4708076 -0.4061506 -0.30349925 -1.0279816 0.0933191 -0.43973824 -0.23978963 -0.44935736 0.5380542 -0.6819385 -0.87937945 -1.4573483 -0.34697774 -1.2184066 0.04650812 -0.9736743 -1.2382468 -0.44998327 -0.14902766 0.39681593 0.091613136 0.6755874 0.36920577 0.28002608 -0.07442839 -0.9075359 -0.9322349 -0.8278291 -1.1375368 -0.086287394 -0.41305074 -0.9738125 -0.8106865 -0.2164324 0.57028687 -0.13382965 0.60434943 1.5605409 -0.094388045 2.0543072 2.0888267 -0.10730177 -0.6925979 -1.3314468 0.0711253 0.3168844 -0.5939014 -0.19559003 -0.9159245 -0.27606642 0.5296954 0.6395445 0.46625546 0.11152852 0.35515478 1.1553466 1.5679377 -0.46183625 -1.4752636 -0.8791576 -0.52207905 -0.4630108 -0.1775305 -0.6851071 -1.7448527 -0.39789253 0.31087413 0.18025494 -0.015893191 -0.17907868 -0.39021474 1.2037607 0.3530627 0.75093013 0.15558794 0.48209253 -0.39278036 -1.5341489 -0.54984134 -1.1763713 -0.865672 -0.91032666 -0.20703177 -0.5498302 0.6994787 0.27411917 -0.3102672 0.3509157 0.5413362 1.1512954 0.100788124 0.013839475 -1.8755858 -1.9471835 -1.5138106 -1.1581895 -0.9587133 -0.72408 0.039137594 
+0.2655536 0.20912734 0.27780163 0.5005239 -0.3929467 -0.39073962 0.68997747 -0.28114867 -0.030789051 0.903621 1.0055568 0.91974187 0.93287635 -0.5901137 0.42117637 -0.028239178 0.4146086 0.766711 0.056175023 -0.3398499 -0.64525175 -0.1718786 0.55026054 0.21018513 -0.6887068 0.31739333 1.5857122 0.7172532 -0.17307656 -0.10687053 0.4703224 0.53016156 0.42433354 0.082219414 0.17878774 0.23113619 0.17447498 -0.46316203 -0.07414455 -0.24828774 -0.5307544 1.0175544 1.8846009 0.67129517 0.35328257 0.56131697 0.6286371 -0.16028543 -0.2774467 -0.46737266 -1.1436111 0.5555589 0.5763477 0.11904423 -0.7030402 -0.11481525 0.99209714 0.8191825 0.62821525 -0.7257333 0.2869634 -0.3806461 0.1337369 0.6016811 -0.4804894 -0.6768394 -1.2537265 -0.743884 -1.4918047 -0.98992723 -0.78323066 -0.47366065 -0.110778786 1.2892164 0.57573706 0.2780828 0.13766941 -0.4876588 -0.5572461 0.7066157 -0.5047975 -0.40421748 -0.2030826 -0.33187494 0.1385277 -0.52379984 -0.91316587 0.20564246 0.5918553 0.9112933 1.0146444 -0.9965859 -0.23677862 -0.6138128 -0.08857286 0.19125019 0.66181374 -0.36628246 -0.63745594 -0.7338011 0.41698742 -0.6396078 -0.4105091 -0.88777405 1.0319741 0.686703 0.2902494 0.7569782 -0.45875964 0.6590497 -0.1553405 0.42167228 -0.24853961 0.34718272 -0.64157826 1.0135905 0.047022697 0.15919384 0.2633392 0.34297147 1.6605926 0.67582095 -0.5358262 0.67377067 0.97797024 -0.1398138 0.8866565 0.62661964 -0.799668 -0.08852595 0.16721325 0.76941776 -0.8758998 0.2439625 -0.37579513 0.7320505 0.6033613 1.5433972 -0.6763225 -0.06245375 -0.8907042 0.0024411832 -0.5088834 -0.5299431 -0.3628758 -0.35241425 -0.28805616 0.48546484 -0.16976687 -1.1666647 0.44220084 1.089552 0.1918446 0.42428505 -0.5981872 -0.48803848 -0.8898371 0.11159187 -0.75131 -0.008072262 0.2009443 0.34911662 0.29328454 -1.1172435 -0.20877276 0.19961467 -0.25070262 0.8052392 0.82128197 -0.39540523 -0.94573385 0.50537837 -0.35292855 -1.2966717 0.13053574 -0.4465895 -0.25852188 0.04011812 -0.3923933 -0.45251283 -0.34872177 -1.2026882 0.3665214 1.0865983 1.9186187 -0.2196125 -0.58682126 -0.7149792 -0.50436866 0.5268231 -0.07194176 -0.8251468 -0.8934988 -0.45575252 0.6223951 0.4525252 -0.34964642 -0.5640666 -0.48815215 1.0133675 2.754795 0.94271356 0.30777413 -0.16325808 0.03721818 0.45958883 -0.9498606 -0.35121766 -0.17576405 0.0027354737 -0.2206376 0.64727014 -0.11570348 0.44246918 -1.0919874 1.4266452 2.78685 0.20823571 -1.0009291 -0.6590832 0.2276835 -0.50296235 -0.38560033 -0.48608172 -0.3667926 -0.36799756 0.48414785 -0.0946934 -0.70191735 0.5990522 -0.3405101 -0.064496934 5.0091662 1.8647856 0.29655224 -1.1390755 -1.8193153 -0.024291452 -0.0134355705 0.17981693 0.41047746 -0.28326282 0.62764883 0.89132804 0.3661629 0.7736536 -1.0688847 0.13118355 2.2068124 2.0853252 -0.49834332 -0.9713015 -0.34099096 -0.4104785 -0.5950208 -0.16943587 -0.034320444 
+-0.019013923 -0.5593278 -0.027655426 0.15936835 1.9508231 0.4179888 0.18382347 8.7720976E-4 0.6041585 0.63353336 0.8586137 0.9861417 -0.22249241 0.23859814 1.0306393 -0.15254892 -0.45547253 -0.15946929 0.43481642 1.1844281 1.2652506 -0.9114141 0.45439672 -0.92445457 -0.51044154 -0.5980822 1.0740143 0.74273217 0.28123623 -0.25998494 0.27141112 -0.310808 0.1687816 0.36144173 0.6729226 0.9282508 1.2282875 1.4944642 2.1318598 2.2798693 0.73654747 -0.543908 0.32156757 -0.59468603 0.5413016 -0.25123644 -0.33983743 -0.5008565 -1.6281133 0.26747704 -0.070319176 0.10498055 0.26886714 0.64451206 1.7145805 -0.39584637 1.328744 0.55130684 1.5316744 -0.3752583 0.38615364 -0.6801982 -0.25383756 0.09997121 0.036812443 -1.0732667 -0.07080488 -0.8428186 -0.28777385 1.4615359 -0.17730002 1.5752655 0.2228389 0.044306032 -0.28438708 -0.8279612 -0.40542278 -0.4508227 -0.4855347 0.11733689 0.16775374 -0.011684492 0.51585674 0.1650439 -0.26230016 1.0843524 0.4377971 1.4341329 -0.40667966 -0.13527119 -1.7408396 -0.4024227 0.9420831 0.51538384 -0.70313305 0.37670416 -0.36990282 -0.29155943 0.3091867 0.4596967 -1.1465932 0.035810772 0.68450165 0.26831222 -0.0351925 1.2034165 -0.3714581 0.7181595 0.63313377 -0.91201806 0.010928747 -0.47688216 -0.7221246 0.05560097 0.82698727 -0.1156754 0.1059059 0.124218844 -0.8364793 -0.6973174 0.78952956 0.6132329 0.52379006 0.8508437 0.1850855 1.1832836 0.060986165 -0.3729964 -0.6796061 -0.97323835 0.11984108 0.09425962 2.0139968 -0.042435423 0.19492005 -0.30046394 -0.104979716 -1.1802115 0.5039797 -0.5024298 0.49689642 -0.6821288 -0.45544896 -0.37709427 -0.81473136 -0.4967065 -0.005886022 0.71667606 0.8754708 0.20909333 1.5011494 -0.87936914 0.86911553 -0.210091 0.7751902 -0.8077408 -1.0505517 -0.88030976 -0.7196946 0.41301703 -0.0031905407 -0.10821255 0.04713516 1.4041843 0.85605687 -0.19094828 -0.500073 -0.5994427 -1.0239124 -0.62293416 0.22036822 -0.24719559 -0.7257256 -0.579403 -0.68912315 -0.028055057 0.8583942 -1.0166314 0.06581372 1.5040034 1.7057898 0.97553074 0.544345 -0.90888333 -0.0058637853 0.050625477 1.0351783 -0.22018136 -0.23649438 -0.5039499 -0.3727144 -0.47446975 0.0076442356 -0.37686425 -0.18941674 0.38914767 0.51185197 0.9048605 -0.44857833 -0.61072344 -0.5234435 -1.7413638 -1.0289229 0.48657188 -0.22008747 -0.47951075 -0.09340978 -1.3659654 0.21456048 0.42270896 -0.8650083 0.20079374 1.4290963 1.2700655 0.30864012 -1.1253992 -1.6627966 -0.055490006 -0.7111064 -0.43003562 0.21568038 0.16530405 -0.17617045 -0.63811415 0.8353782 1.0249264 0.121783346 0.7416036 1.5801564 1.0942514 1.7873352 1.2845874 0.20780191 0.15106182 -1.0947957 -1.4064367 -0.7041823 0.507342 -0.312557 -0.37684336 0.7351317 0.75828403 1.0594968 0.63269114 0.38714868 1.7092388 0.45921358 1.0377389 -0.90148944 0.65743774 -0.09331646 -0.060397107 0.1864507 -0.50751346 0.4991738 0.4223295 -0.0138865085 
+0.18741937 0.05844517 0.107588954 -0.8741877 -0.33464214 -0.14754 1.9017572 0.62622714 1.3705214 -0.08919245 -0.35722572 -0.7956719 -0.18739957 -0.57257545 -0.07492495 0.1490324 -0.19184431 0.20078819 -0.17834684 -0.12593341 0.53071487 2.641591 0.7416391 0.029856639 -0.52545595 0.68071944 -0.628959 0.3205509 -0.14747715 -0.67109144 0.89112246 0.53295016 -0.08654375 0.16116631 -0.7502155 0.8142805 -0.5614757 0.61262417 -0.6215157 0.36224598 0.21214853 -0.07439313 0.773532 5.6553434E-4 -0.018394843 -1.0109906 0.2953082 0.25910404 0.65029526 0.43499723 -0.60934645 0.7752299 0.004911281 0.3752516 -0.1202372 0.46082577 -0.24737115 -0.19165471 0.34166917 -0.2630121 -0.5121444 0.04343497 0.92088044 0.57845634 -0.11260352 0.40832257 -0.2519616 -0.7626336 -0.24092267 0.31800893 -0.5379481 0.32397375 0.1151144 1.1187769 0.4342471 0.41548344 0.08669351 0.5618479 0.48308378 0.48131534 1.0433762 0.72784114 0.3679485 0.75082517 0.8353672 0.57721716 1.2699949 -0.67829967 -1.555115 -0.13472863 -0.2983059 0.7487707 0.20740932 0.7476599 1.8842788 0.7028376 0.9125145 1.1639436 0.39781398 0.63401926 1.8934692 1.392644 -0.2196824 -1.1790953 0.54124874 -0.40006465 -0.36222944 -0.037199058 1.429659 1.2408478 1.2483109 1.2455537 -0.011036427 0.85180753 1.7580289 0.7956996 0.9754138 0.90732765 -0.5544313 0.8570376 -1.4113396 -0.3677924 -1.2973725 -1.269597 0.37990695 1.0051597 1.6084625 1.9070588 0.7628624 0.6392008 1.7875148 1.7688146 1.147904 -0.32483572 0.08062799 -0.6931679 -1.1542838 0.4153268 -0.44436115 -1.4188575 0.89936477 0.45710486 1.5991627 0.75049907 0.099247605 -0.055834766 0.93848056 0.76077604 1.1250112 0.20561181 -0.3244176 0.18837464 -0.9486599 -0.3582709 0.45190865 -0.4391759 -0.74608123 0.7303873 0.9377955 0.49985382 1.6315415E-4 -0.71048754 0.50759405 0.22156022 1.4022765 0.83346313 0.20095845 -0.045196187 -0.13318294 -0.7125806 -0.42979443 -0.47496998 -2.564434 -1.8641908 -0.040227607 1.4219406 0.8213356 -0.6914582 0.016733743 -0.70375407 0.13795327 -0.1936324 0.53349614 0.6583703 -1.0996759 -1.588928 -0.096093215 -0.7258583 -1.1416292 -0.9010278 -0.64513355 -0.7005376 -1.0596285 -1.3595951 -1.1782464 0.107730724 -1.3089224 -0.8516331 -0.32558545 0.3778468 0.035222515 -0.11861295 -0.63473344 -1.3811933 -1.4265987 -2.0142145 -1.6190739 -0.12815966 -1.194475 -1.6335547 -1.0203099 -0.13419607 -1.0688349 -0.7662679 -0.17951438 1.1670516 0.9053126 0.101322144 0.011870901 0.40959594 -0.55034125 -1.0703675 -0.98098046 -0.9508273 -1.6664845 -0.5509703 -0.6564642 -0.6663612 0.5168781 -0.7112692 -0.96215266 -0.06871413 1.1977731 0.64040107 0.6185867 0.14775455 -1.6525166 -1.4229093 -0.96814746 -1.5374098 -0.40503716 -0.9312733 -1.2905409 0.30373734 0.056848325 0.30997863 -0.3582716 0.7434484 -0.05940083 0.060815886 0.69049716 -0.09523203 -0.9617932 -0.98904926 -2.5074627 -1.5517025 0.039358087 
+0.1306675 -0.08810504 -0.19396697 -0.29684123 0.8419081 0.07944866 1.0660057 -0.16770437 0.3305021 0.1258698 -1.336586 -2.1338668 -1.8502316 -0.66511905 -0.58402234 0.13700725 -0.36705044 0.14300336 0.35747337 0.16752508 0.3771936 -0.34320626 0.30910847 1.2654301 0.9092736 0.11327631 -1.1850528 -1.6449164 -0.2559122 -0.77889585 -0.5960517 -0.48859814 0.05034162 -0.6584938 -0.99436843 -0.3694262 -1.2503501 0.39336658 0.77176684 0.47463343 -0.935319 0.05556002 -1.3496398 -1.4228431 0.73368686 -0.34985778 -0.08608003 -0.78112626 0.5887329 -1.3421826 -0.08992101 0.14594577 -0.50157607 1.4557325 1.8198694 0.0013160317 0.60683 -0.55778193 -0.5575817 -0.09262472 1.1252712 0.58344275 -0.23745406 -0.7179646 -0.12332561 0.20693398 -0.5665966 0.518605 -0.25163898 1.3262067 0.3251829 0.3713209 -0.4640877 -0.95281464 -0.9626222 -0.07193979 -0.9993373 -0.6258432 -0.014317402 -0.6060061 1.0015337 -0.56274146 0.87612915 1.2567742 1.5766723 -1.0615394 -0.1964796 -0.12142464 0.24061316 -1.3286275 -0.9467024 0.29178062 -0.20374396 0.033070173 0.008572113 -0.51294863 -0.10878155 0.5312089 0.009669434 1.5473503 -1.3356566 0.36500567 -0.4326106 0.68197703 0.064620145 0.18814391 -0.5316942 -0.25220403 -0.2076089 0.21329527 0.7067419 0.6407575 -0.61923915 1.2894835 1.2610555 -0.08628677 -0.42339805 1.2945117 -0.38575566 -0.039782163 0.11252348 -0.5577557 -0.7909287 -0.37564313 0.13342752 0.66995835 0.7468149 1.2021754 1.6553942 1.6992449 1.8834252 0.9232681 0.37345597 0.101350404 0.3771182 -0.93183315 0.020668877 -0.5793435 -0.092787206 0.84792066 0.44711718 1.1221637 0.984094 1.2014402 0.049333956 1.951225 1.6126589 0.5021369 1.4279804 0.9476543 -0.2252602 -0.48744276 -1.3472203 -1.1088169 -0.8772582 1.1987839 0.7978504 1.5244353 0.73576343 0.48078197 0.4330286 -0.03606264 1.3125789 1.4080673 0.7606048 1.9725347 -0.3275315 -0.81802684 -1.2370794 -0.04448072 1.0570064 -1.0670487 -0.01366351 0.3491928 1.0166076 0.50396436 0.6142331 0.44755024 -1.2607465 0.88886386 -1.6459436 0.30220723 -0.39302492 0.061551835 1.0141339 0.9072057 0.32577202 0.06940849 0.3417613 -0.9067647 -0.2689841 -0.010047809 -0.016350148 -0.401158 -0.9121348 -0.9606257 -0.61177754 -0.7954506 -0.07191235 -0.63594514 -0.23767728 -0.33685645 -0.97194004 1.781143E-4 0.5901478 -0.10614153 0.6038026 0.77489203 0.14725341 0.36429745 -0.38412973 -0.8017012 -0.59188765 -0.8254027 0.32416984 -1.1293834 0.72122455 -0.89456296 1.1095755 0.7870492 0.35010624 -0.25735247 0.6429504 0.65076756 -0.8703204 -0.07841424 -0.5781882 0.1701073 0.14269476 -2.8296328 -0.37793267 -0.53420335 -0.12929243 -0.8566317 -0.8912634 -0.63812417 -0.52143586 -0.6853084 -0.14494348 0.100307934 -0.12786727 -0.24725899 -0.5108697 -0.23390871 -0.5116105 -0.92768705 1.1467588 -1.2634263 0.27012143 0.7013687 0.48235458 -0.39544111 -0.5257143 -1.0676401 -0.33533847 -0.6315007 0.049996994 
+0.4210941 0.77483416 1.3594465 0.43669483 -0.3352457 -0.72765136 -1.0211859 0.42879608 -0.2534454 0.6383494 -0.6071047 -0.123940825 -0.458861 1.4483968 0.28250518 0.43770674 0.7949274 1.32611 0.44338778 0.36182818 0.42772445 -0.8841169 -2.342006 -0.8975124 -0.17597891 -0.2925875 0.022505436 0.0673628 0.33149216 1.3377577 0.39020646 0.7783739 0.9203709 1.2941694 0.25351226 0.16446339 -0.19610426 1.151762 -0.14623557 -0.40543097 -0.30726853 -0.89575356 -0.08694243 -0.02517721 0.57705283 0.8107148 0.19896336 0.772632 0.62407374 1.0977383 0.4058518 -0.27118015 0.38478938 0.04023144 -0.47299173 -0.4752893 0.11547797 -0.077342875 -0.058772583 -0.3066454 0.17875512 0.62061775 0.33977917 -0.36598167 0.77629983 1.4175409 -0.21028851 1.2956944 1.160431 0.23782459 0.11092974 0.7030824 -0.03260208 -0.14684784 -0.47262987 0.49788982 -0.33076137 0.77042115 0.8705107 -0.33558515 0.6947941 0.588054 0.19616725 -0.45370013 -0.74690586 -0.62219197 0.6539602 -1.4232413 -1.2672135 -0.41534135 -0.8763528 0.14001098 -0.055034157 1.1023037 0.96821004 0.43608975 0.40904504 0.25809816 1.5323129 -0.6495836 -0.3819064 0.5494483 0.7941229 0.19491106 0.053876277 -0.8309649 -0.4689027 -0.9852825 0.6139256 0.42964518 1.5733179 0.39989507 -0.18118137 -0.24074502 -0.18040209 -1.2791779 -1.1357889 -0.3394489 0.31559852 0.35075733 -0.9291603 0.37264585 0.9622106 -0.7675911 -0.2784752 -0.80266756 1.3543022 0.5034601 0.14490469 -0.43616825 -0.82071334 -0.5963965 -1.0204768 -0.97799283 -0.31616393 -0.35395908 -0.23198141 0.72689754 -0.7445571 -0.9527641 -0.48993194 0.6126473 0.6674658 0.060332883 4.89312E-4 0.19321942 -0.21504353 0.46539193 -0.5137827 -0.18670382 0.42881304 -1.2561538 -0.28432533 0.054970324 0.31906644 0.6543109 0.7446261 -0.33894786 0.78154474 -0.18325603 0.4521652 0.6722504 0.78073466 -0.30515453 0.13005808 0.69470745 1.5532869 0.05543797 0.2428854 0.74492663 0.82593 -0.80344 0.9540927 0.14438836 0.6988349 0.3114309 -0.15200575 0.84485173 0.14251311 0.24640386 0.7768309 1.1810362 0.93135256 -0.50187516 -0.061778985 0.59501654 0.6780112 0.81371427 0.3908225 -0.86442715 1.2047373 1.3188055 0.7961464 0.85895765 -0.18715236 -0.06702574 1.8268923 1.4873521 1.5049443 -0.043345466 -1.11349 -1.6473024 -0.22649497 -0.8012598 0.39231023 0.35135978 0.98484087 1.2620138 0.5711644 0.27800778 0.46492106 1.04483 0.2451862 0.1478414 0.27078772 -0.90838677 -2.5203257 -0.6743923 0.6178843 0.036686473 -0.82106036 0.17562672 -0.36127123 0.42664292 1.2804699 0.054801844 0.43787256 0.025435165 -0.17659584 -1.8994148 -1.4006037 -1.4436747 -3.0916028 -1.3738126 -0.39677885 -0.9717314 0.56512487 -0.2759742 -0.15146157 0.46004313 -0.06915695 -0.12653224 0.6501409 0.87865096 -0.11854227 -0.8397493 -0.5506388 -2.216401 -1.7679112 -1.7093164 -0.48267815 0.66151696 -1.1707624 -0.7387133 1.1608672 -0.23390184 0.04481526 
+-0.06614741 -0.8926074 0.05276698 1.2399124 -1.4459828 -0.3377294 0.50482833 -0.9844524 -0.13597798 -0.84957665 -0.38065082 -1.1380565 -0.124213524 -1.2788005 0.1844367 0.41543773 0.7815851 -0.5048512 1.1194943 0.6624772 -0.30422455 -0.63167226 -0.3420317 0.2389154 -1.063399 -1.2762705 -0.6999134 -1.7727294 -0.74758184 -0.71677494 -0.8482182 -0.5533826 0.68549556 -0.65717685 -0.7988141 -0.5636738 -0.59556884 -0.6642837 -1.4485155 -1.3983487 -0.8643846 -0.7271305 -0.31838098 0.48474824 -0.71174 -0.32922897 0.15820013 -0.61629933 0.19805174 -0.16302434 0.82739514 -1.3442092 -0.5520568 -0.6563903 -1.4083201 -2.19293 0.026580691 -1.5793334 0.06845715 -1.1804434 -0.56006396 -0.12925798 0.20952812 0.600184 -0.45223188 -0.16853012 -0.8032871 -0.3958787 -1.2713045 -1.1402345 -1.3528425 1.171329 -0.78496253 0.024725191 -0.49281192 -0.059761062 -0.36873296 -0.32990417 0.46543545 0.84886724 0.13418995 -0.15525001 -1.739297 -0.7640571 -1.9102812 0.42043835 -1.8117547 -0.6264603 0.69193476 0.18242198 0.42873016 -0.5019057 0.056793384 0.79430294 -0.08620918 0.2815069 0.6784726 -0.34102148 -0.2875736 -1.1952902 -0.628488 -1.801299 -1.2676896 -1.8025494 -0.11287571 -1.030694 0.025024781 0.7863675 -0.625579 -0.96351177 -0.995239 -0.7757474 0.40900737 -0.56083745 -0.1608678 -0.37373102 -0.036708973 -1.813104 0.14581451 -1.6458843 -1.7676811 -0.508144 -1.2458857 -0.74957746 0.20277797 -1.3085921 -1.809385 -1.3513765 0.21405584 1.3439068 -0.08889395 -0.39016798 -1.1737773 1.6099886 -1.5271802 -0.4115741 0.5421425 -0.9341052 -0.16714327 0.468465 0.13337651 1.2134591 -1.2681372 -0.44610316 0.28835052 1.3327407 -0.26625508 0.93017167 1.5444958 0.95526314 -0.33739418 -0.99384886 -0.4981343 1.3509305 -0.6409635 0.286561 0.04807017 -0.16463104 -0.7979799 -1.1177033 1.7890214 1.8892144 0.68588984 0.51101744 0.97111213 0.20866822 0.83101887 1.9672662 1.3243285 0.6483589 1.123383 1.220378 1.3064064 0.9077638 -0.7821262 -1.6894144 0.69090945 0.86924183 0.5950807 1.3171443 1.7528026 0.67553115 2.1554809 1.4707098 2.4038281 1.6458343 1.3644614 0.9931186 0.9715952 0.42306644 -1.8463933 -0.18495426 0.56331486 0.024575418 0.30241883 1.3717574 0.62928313 0.621776 0.80487674 1.618193 1.6118346 1.1746613 1.2526987 1.6436434 0.28303456 0.46151245 -0.27341285 0.5921522 0.61520517 0.025880096 1.1226492 -0.4542963 1.1819191 1.5735483 1.1764187 0.70955795 1.1176461 1.023221 -0.49247834 -0.19491778 -0.18913862 0.060736127 -0.6310814 0.80882835 -0.48169 -1.0323639 0.42778757 -0.3811688 -0.3061145 0.07213724 1.0811404 0.51909345 1.3032093 -0.35248837 0.24872433 -0.059474163 0.21838465 -0.6043323 -0.5254696 0.77191216 -0.33008608 -0.3733788 -1.1724132 0.41638252 -1.0570074 0.8221327 -1.0082321 1.1047982 0.37184864 1.0501375 0.03284817 0.04258604 -0.8418931 0.68144476 -0.45083743 -0.049162135 -0.009801069 
+0.99136937 0.09246654 0.40818566 0.6898116 1.136634 0.09465015 -0.56463534 0.75223464 -1.0390077 -0.794109 -0.17543107 -0.23912679 -0.5593342 0.49641782 0.34359542 0.35128918 0.28790897 0.7145811 0.45953587 -0.40440863 0.32557824 -0.22195394 -0.7860361 -0.7698743 0.1644437 -0.5036998 -0.16777912 0.81722176 0.79438764 0.9637863 0.1870715 -0.4959964 0.7790271 -0.3065376 0.768382 0.1646769 1.0312743 0.86403686 -0.31791478 0.4164355 -0.19857281 0.4326466 0.80954033 0.111520626 -0.0014193997 -0.55442333 -0.65743667 -0.27334628 0.98518497 0.07175062 0.7445575 1.0181185 0.76550007 0.97648156 0.09430475 -0.55809706 -7.3163904E-4 -0.31632668 -0.77268726 -1.18394 -0.4464234 -0.7718449 -0.58454543 -0.35792625 0.7643546 0.34281516 -0.15706573 0.73725224 0.06572232 -0.09317381 -0.49958158 0.2207807 0.2510782 -0.6656277 -0.36778265 -0.62175554 -0.55392456 -0.076036684 0.55512685 -0.029001923 -0.4907282 -0.14346306 -0.8095675 0.17758994 -0.42599648 -0.7750492 -0.9804896 -1.7508664 -2.0438032 -1.2802098 -0.1680486 1.0452222 0.5926337 0.012853365 0.073275864 0.46175304 -0.71636605 -0.5204106 0.044962384 -0.27308643 0.50472385 0.37090364 -0.8469607 -1.6211667 -0.8287603 -0.42990693 0.22054495 -1.1086417 -0.24006237 -0.6042538 1.2089908 -0.0017449564 -0.7170346 -1.2352537 -0.35825136 0.42084396 0.33832428 1.5152899 0.3795515 -2.108959 -2.558984 -0.79628086 -1.3921136 -0.25077218 -0.6782765 -0.073621 0.23745659 -0.50686175 -0.57528526 -1.0680438 -0.53323215 -0.89074993 0.1941403 -0.15798885 -0.3711014 -0.4342436 -1.6357392 -0.54980314 -1.3744549 -0.28576785 -0.92837 -0.045658257 0.41462237 0.6954067 -0.24008644 -0.115207106 -0.2582881 0.3740109 -0.19415247 0.821061 0.8701913 -1.3941127 -2.821885 -1.6139889 -0.44020027 -0.27241728 -0.15551184 0.04789109 -0.10775649 0.755617 -0.03876054 -0.50327694 0.016925905 1.1023417 -0.46971074 0.88026744 0.12574364 -1.5785416 -1.2478677 -0.28868246 0.22684672 0.6522745 1.3196474 0.6582475 0.14248073 0.4581836 0.12507701 -0.2655937 0.4034478 0.38806748 0.7328675 -0.18048367 -1.2674963 -1.2245164 -0.4558096 -0.5719185 0.25579906 1.830696 0.3053418 0.1671748 0.23435274 0.5492895 1.5517159 0.1227049 0.32677802 1.1780509 0.006964192 -0.53909475 -1.9572576 1.3261793 0.08825341 0.9409628 -0.10142962 0.63817495 0.6267152 -0.022781461 0.35748106 0.9751376 0.6750582 0.7796589 0.81998575 -0.2720885 -0.62825286 -0.16573223 -1.4242421 0.5944467 1.1269808 0.10636902 -0.57705986 -0.79921365 0.3948552 -0.20226131 0.4685862 0.7693531 0.24259667 1.3187951 0.317214 -0.500581 0.27402875 0.01751779 -0.39377698 1.058657 1.4036154 1.4066471 -0.05741865 -0.036457647 0.6337977 -0.28971574 0.8763883 0.15645993 0.22220317 0.07507053 0.2076764 -0.80390394 1.0592434 0.40609998 -0.43888524 -0.1763856 1.6350197 0.88246363 -1.3624909 -0.64572537 -0.028769583 -0.572493 0.9075763 0.43909055 0.03335878 
+-0.039897453 -1.0473305 -1.9738395 -0.08066083 0.4563154 -0.13469718 -1.0974445 0.28575954 0.8151633 0.35870752 -0.32288024 0.038713247 0.10632907 -0.91031206 -0.7445392 0.15077108 -0.6562413 -1.6421809 -2.3477588 -1.17706 -0.6693971 -0.16072616 -0.6345176 0.19711642 -0.07223625 -0.18081397 0.17301075 -0.55957085 -0.059711598 -1.0209014 -0.43979123 0.14343801 -0.95046276 -0.86193275 -0.31555238 -0.9933889 0.15957284 0.5115487 -0.25687563 0.054727387 0.52195686 -0.64632154 -0.4230632 0.5534575 -1.2414242 -0.8522004 -0.47469336 -0.23470555 -0.52015734 -0.55574405 -0.27578256 -0.3890521 0.24994518 0.3679207 1.2684208 0.64534587 -0.24598277 0.49023935 -0.7341304 0.67510086 0.26612106 -0.11576529 -0.02725733 -0.23683588 -0.0025211372 0.02948535 0.4021133 -0.29726163 0.10534527 1.0569327 0.388026 1.9897652 1.4538614 -1.6077824 0.1329702 -1.5669914 -1.4391166 -0.32774863 -0.7142928 -0.53601605 -0.16672859 1.1276579 -0.17643255 -0.98151994 0.09354474 0.96313804 0.6437594 0.6296946 0.34994122 0.7457549 0.14358687 0.26462686 -1.3088158 0.024541581 -0.43706462 -0.6511224 -0.11883346 -0.32913604 0.29359195 -0.5068262 -1.695331 -0.7313914 -0.52220166 -0.2495566 -0.14114481 -0.13790736 0.8967666 -0.40110245 -0.36840284 -0.2969995 0.3566827 -0.72135484 -0.41681522 -0.5289749 -0.3431689 0.638472 -0.26084358 -2.1944 -1.8794001 -0.21858898 -0.15911117 0.22400767 -0.30488864 -0.086543284 -0.24934469 -0.20108935 -0.33416805 -0.48851737 0.68313515 0.023350602 -1.2734734 -0.37844938 -1.8323437 -0.16246755 -0.56913996 -0.55498374 -1.4006218 -0.74688464 -0.63984466 -0.76999414 -0.35630453 -0.7868165 -0.0064486037 0.14455482 0.19096488 0.8459263 -1.5671661 0.30203977 -0.13885438 -0.99505806 -0.78312266 -2.2602646 -0.19843014 0.19578306 -1.7278367 -1.1866204 0.373928 -0.47077668 0.51647496 0.34682763 -0.58979386 0.58315593 -0.023061303 -1.8893011 -1.1615055 -1.5630709 -0.88493294 -0.22250398 -0.10023446 0.9788492 0.6778828 -1.1908646 -0.04219563 0.39587852 0.22889104 0.73442614 0.3023371 -0.21472123 -0.057378404 -1.6932135 -1.4380265 -0.31013304 0.0071681673 -0.8875245 -0.4263981 -0.5434434 -1.8887312 0.5916187 0.2406423 0.292083 1.3467373 0.51212585 0.44196978 -0.9748935 -0.1733285 -1.0500205 0.44180337 -0.0028115935 -0.14590004 0.79631627 -0.1076867 -0.59319293 0.77230585 -0.4059036 -0.5149853 0.46749485 1.0264856 -0.62003356 -0.1214978 0.08076122 0.26451445 -0.022219539 -0.3736543 -0.17178112 1.6801683 1.6244713 -0.2459859 0.044527866 -0.20127755 -0.3286216 0.4934219 0.49906483 0.7518498 0.41540352 -0.011397177 0.7633044 0.09447985 -0.46327302 -1.8151445 1.208857 2.09573 0.92051345 1.5730945 2.0012982 0.444456 1.6042355 0.80587304 0.87949663 -0.053663764 0.7995906 0.10809081 -0.08975346 -0.022907007 0.42839795 -0.18389878 1.1502995 0.15184148 0.67377484 0.5720212 0.7607991 0.61176366 -0.2233229 0.23642074 -0.4032493 -0.05701997 -0.049058806 -0.029168418 
+-0.3120106 -0.6726388 0.60258967 -1.3128567 0.76199263 0.3557241 -0.9529979 0.7796131 0.04189878 -0.5133918 0.30820948 1.4955852 -0.90046144 0.4743241 1.0590048 0.69147533 0.50355023 -0.27380842 0.22927956 -0.61967474 -0.5505922 -0.59860414 0.5804434 -0.33480558 0.05921459 -0.06914764 -0.728996 0.083487235 0.30173978 -0.17253156 0.17440605 0.10289021 0.4643948 1.109889 -0.39753604 0.5432495 -0.9563993 -0.6395443 0.57042366 -0.45023495 -0.74501365 -1.8015321 0.1269381 -0.18787786 -0.6053487 -0.7521008 -0.7985911 0.21157682 -0.5494122 -0.13889028 -0.6792477 -0.7025897 0.2494581 -1.58277 -0.8791207 -1.0855435 -0.96735644 -2.616132 -1.2924019 -0.9570277 0.20615286 0.3274567 -0.5841676 -0.43353394 0.35690147 0.14250748 -1.314844 -0.7796601 0.16459872 -1.1619126 0.1213033 -1.0912149 -1.2173625 -0.9434216 -2.0208557 -1.6634464 -1.4461288 0.5500558 -0.2910044 -0.115702674 0.16718198 0.44069552 -0.48567572 -0.17897172 -0.24855797 0.082272016 0.939331 -0.3249579 0.4910915 0.12885134 -1.6661794 -1.6972398 -0.85704464 -2.2558632 -1.0548764 -0.0044229673 0.31638232 -0.28892875 0.4634995 -0.91866976 -1.4944475 -0.3021254 -1.488098 0.9607544 1.012584 0.9903948 -0.7921884 -1.5839449 -0.9420013 -3.0950303 -1.6541036 -0.21768336 0.11262922 0.07333207 -0.8664438 -1.2089671 -0.48067153 0.6230414 -1.2906172 -0.063141234 -0.61222774 -1.2940862 -0.863175 -1.5922889 -0.17285223 -1.5164113 -1.9732398 -0.38451457 -0.7511857 -0.23926823 -0.309276 -0.74424756 -0.5115918 0.04487617 0.9503431 2.2261858 1.2033042 0.2983033 -0.20054303 0.7478195 0.44720647 -1.3701164 0.025076078 -0.18550505 -0.5416217 -0.7460135 -0.5745824 0.18354633 -0.1688947 0.7483712 -0.37131009 1.5588146 1.3242908 0.528965 0.10354441 -0.10095797 0.78019553 1.2563998 1.8420073 -0.053465147 0.22566733 0.25211 0.06683271 -0.049312428 0.6732234 1.0140339 0.49816212 1.5720763 1.1911975 0.5771229 0.86190647 1.5578518 1.8198541 -0.22855377 0.46666124 -0.73833746 0.65381795 -0.57841384 -0.19229726 -0.80294025 -0.9010407 -0.6571466 -0.17809997 0.23394789 0.65087783 2.4263923 0.82482314 2.0951633 1.7224741 1.3204674 -0.088583775 -1.1698322 0.792496 0.2713486 0.9578671 -0.29220566 0.993994 -0.72219205 -0.7276477 0.44314006 0.31814057 1.0070264 0.50891143 0.12557253 0.6881946 0.84876996 -0.25030148 -1.2812297 0.30205172 -0.28698242 -0.5528458 0.64715827 0.16514951 -0.3698934 0.14115977 0.094269656 -0.31602782 1.157565 1.0699493 1.049596 -0.17961133 2.5326138 0.28848273 -0.20890869 1.4571124 0.71821654 0.80710626 0.33683085 -1.4096146 0.102418914 -0.18468335 -0.27584943 -0.2157589 0.7233689 0.66270155 -0.1307133 0.87076336 0.76056916 0.6978896 0.9603978 0.47199434 0.8328178 1.2448459 0.6661133 1.0701189 1.152887 -0.26890662 -0.09190631 -2.049034 -1.3874335 -0.28492087 0.4319162 0.8455813 0.04454681 0.43607768 0.10287074 -0.0077168234 
+0.83506364 1.3421296 1.5210059 1.3019994 0.9610961 -1.739915 -1.9840068 -0.04264199 -0.6492746 0.68140537 0.584721 -0.50890785 0.8602347 0.101917446 -0.12653388 0.21392709 1.1713158 0.944732 0.21204717 -0.5445348 -0.024603257 -2.1586475 -1.5385782 -1.9237825 0.17006885 -0.6225963 0.34583613 -0.21739545 -0.07090213 -0.011476703 -0.48340118 -0.6838255 -0.23365282 0.02912118 1.0778679 -0.25725135 -0.3123358 -1.4048775 -2.0190563 0.26838276 0.58599436 0.24957927 -0.016513485 0.8923641 0.559474 -0.034272183 -0.7988706 0.09069047 0.5885798 0.2722873 -0.018969087 0.7194841 1.0880713 -1.2998073 -1.0968001 -0.22436075 0.50076574 0.37027344 -0.17653486 0.08530361 -0.7507347 -0.26017633 -0.30614597 -0.6397796 0.32650164 1.5644566 0.6466497 0.21210513 0.27389944 -3.2060852 -2.481006 -0.41008386 -0.2615226 1.0012318 -0.16333133 -1.0771081 -0.91497767 -0.21408942 0.07782232 -0.33465534 -0.1546389 2.1037476 0.39766496 2.100532 -0.056788098 -0.8399829 -2.4874034 -1.789557 -1.3241444 -0.64177966 -0.1171624 -0.24609071 0.10654199 -0.3102452 -0.520529 0.18710357 1.0847559 1.2085757 0.67875844 1.3253442 0.63724583 -1.4978675 -1.997485 -1.4112675 -1.233663 -1.0129968 -0.96145684 0.42385033 0.5533441 -0.21198024 -1.0468575 -0.7829186 0.29263023 1.0066077 0.6659909 2.012192 1.6455915 -0.52581203 -1.5679635 -2.0220509 0.026615676 0.38267308 0.75380784 -0.45124176 0.015365636 -0.3559177 -0.98606944 -1.1616826 0.17799117 0.9295973 0.5999197 0.14045523 0.4007424 -0.13226959 -1.8109767 -1.7856138 0.14218451 -1.3100963 -0.22484827 -0.42157724 -0.29283652 -0.8557078 -0.8586125 -0.10246858 -0.07855992 1.4495137 0.38129178 1.2284194 1.8776028 -1.2727954 0.2659428 -2.6059823 -1.1936778 -0.44642913 -1.1384927 1.1437601 -0.7967337 -0.5350143 -0.54894686 -0.49834546 0.7520217 0.52263373 0.85001284 1.1398795 1.004755 -0.9312969 0.23547858 -1.9469633 -1.7580523 -0.082218155 -0.80273765 0.047082074 -0.94762677 0.20558406 -0.031200768 0.021163927 -0.74074316 0.4340175 -0.47145703 0.5286464 1.0852997 1.2367783 0.48478878 -0.9654492 0.4917852 -0.9244092 -0.9365091 -0.29637763 -0.29930514 -0.61317694 -1.3450433 -0.31489068 0.35420752 0.36446935 0.0041762735 0.9440381 -0.05520865 0.24927129 0.6771713 -0.33180583 0.3055281 -0.23946442 -0.67399293 0.7612811 -0.32506862 0.8955687 -1.2064948 -0.45044944 0.40118122 1.0874803 0.55278087 0.5813416 1.6123616 0.07771178 -0.44136363 -0.10084999 -1.1649927 0.1125998 -0.36914265 -0.23696212 -0.10186324 -0.06214986 -0.08817334 -0.3184891 0.6435502 0.14844123 0.18915746 0.2107515 0.19991894 0.3250235 0.5507905 0.58663964 -1.2015544 -0.20834622 -0.015881917 0.20038559 0.120813616 -0.0806207 -0.26918548 0.26010352 0.7302696 0.70229346 -0.11256377 -0.42905158 0.67258906 -0.3096032 0.32874584 0.06332257 -0.20829864 -0.4936469 -0.4174535 -0.0886893 1.0078698 0.5971958 0.26237556 0.32907897 -0.02251101 
+0.26627624 1.2794242 0.10201574 0.24746257 -0.23607011 -0.31842032 1.4573634 -0.9079472 -0.12430162 0.9856307 1.1890104 -0.08302925 0.68327427 0.97976995 0.22728282 0.36401814 0.49890426 1.5966877 -0.16835497 0.440177 0.70625436 0.65729636 -0.47176278 -0.24504955 0.41123194 -0.31326038 0.33909675 0.1006596 0.21352912 0.5775627 0.41820878 0.4948848 0.1901451 0.48021165 -0.1986007 -0.2643754 0.28204012 0.29747897 0.98829967 -1.2417984 -0.060544103 0.009890452 1.4805177 -0.8054715 1.1026652 0.7458687 0.34330663 0.3805003 0.08593417 -0.1393559 -0.5471644 -1.1897794 -1.2021387 -0.36041594 0.1575728 -0.4815413 -0.6868118 -0.37451565 0.31544405 0.21520571 0.6526446 -0.899275 -0.052225575 -0.7244397 0.678072 0.05852802 -0.4350725 -0.886178 0.36397865 -0.102070615 0.16155972 -0.37161672 -1.4925286 0.44666424 -0.22629082 0.99753165 1.289759 0.16665909 1.1053238 -0.26616535 0.4702175 -0.059588015 -0.26468447 -0.39551204 -0.57120687 0.4127524 0.22469702 0.19215158 1.6001155 0.8798971 0.46559018 0.4933919 0.4031975 1.0216298 0.48250702 -0.9872642 -0.73771125 -0.57839656 -0.48791656 0.020454284 0.66101485 0.49601507 0.42649677 0.74785995 0.39965534 0.8877099 -0.0538483 1.5209944 0.7498982 0.5595456 1.0149499 -1.3384172 -0.37910232 -0.9881384 0.66690034 0.09498336 0.019755524 0.2624524 0.3504068 -0.12533778 -0.6711226 -0.09526164 1.6328859 0.31502897 1.0187763 -0.23861068 0.3264509 -0.41669607 -0.064021826 0.21477923 0.53160363 -0.101083346 -0.06801364 0.30233788 0.13410288 -0.21594062 1.5753762 -0.584327 1.2636567 0.936136 0.8104549 0.9259895 -0.27314115 0.13179111 -0.329048 0.20315674 1.1487744 0.3896666 0.37655944 0.29076 0.4436086 0.5410485 0.31306154 1.2307329 1.2451975 2.1324236 0.70392454 -0.43786788 0.93273205 -0.0046542175 -0.68098193 0.3633843 0.42139354 -0.80391634 0.8775776 0.33957165 0.5100352 0.8453441 -0.27119488 0.95969516 0.45136046 -0.08584012 0.05256442 -0.40977988 0.33684868 0.09168009 -0.67006814 -0.31317982 -0.9014017 -0.74368525 -0.68812495 -0.45921516 1.1459609 1.6853166 0.14699925 0.33582166 0.61561865 -0.1326604 0.8583575 -0.3137047 -0.27996 0.930401 -0.14802364 -0.19956206 -1.2979473 -0.18164228 0.56689984 -1.5888208 -0.27858996 -1.0993297 0.7438903 -0.7486228 -0.49765107 1.1147417 -0.021733899 0.9812515 1.1208563 0.18688397 0.2289556 -1.0049201 -0.9808243 -0.5221787 -1.0764918 0.31901884 -1.7285892 -1.4299401 -0.6043177 0.95149577 0.11063148 0.8391988 -0.14575419 0.47303125 0.3364003 0.6852922 -0.166354 -1.0250744 -2.3178432 -0.2509298 -0.32924733 -0.28221187 -2.6196456 -1.883239 -1.3955524 -3.0056043 -1.4162631 -1.7074177 0.255873 0.4454009 0.42515004 0.8183279 -0.29623544 -0.50075257 -1.4718046 -0.46793982 -1.2258286 -0.13568209 -1.0516437 0.60931015 -1.4979763 -0.57499593 -0.5174677 -0.009882827 0.843424 0.54160523 0.13642317 0.45373288 -0.022189317 
+-0.02171785 0.603866 -0.36583036 0.58430374 0.36794236 0.1592504 -0.104343645 -0.8456701 -0.037794493 -0.31476888 0.5072387 -0.6236462 -0.09010266 -0.2944715 0.10946082 0.47240978 -0.21059136 -0.4043218 -0.79813564 -0.002387006 -2.2281737 -0.87775344 0.0022188618 -1.0328627 0.97783536 0.88703305 -0.61239314 0.5263094 -0.044581853 0.041845873 0.6156344 0.057307716 -0.8777092 -1.1526065 -1.1508079 -0.18852797 -0.86723113 -3.7178528 -3.128753 -2.852161 -2.2956445 -1.3032941 -1.4694724 -1.4875205 -2.1135542 -1.2859925 -0.56537014 -0.026899062 -0.6589382 -1.3601643 -1.2287797 -1.7440923 -2.4108098 -2.1365104 -3.0533073 -1.8641765 -3.7451322 -3.1614501 -2.9145923 -1.7408599 -1.3947519 -1.752016 -0.79600793 -0.5607197 -0.4435104 -0.29960564 -0.7684002 -1.4491597 -1.2988256 -1.7022371 -1.3784579 -1.063967 -1.7639692 -2.595215 -1.1966287 -0.948805 -1.5818723 -0.9132796 -0.5368405 -0.14898358 -0.9266239 -0.5311515 -0.5221394 -0.22751202 -0.5290409 1.4305174 -0.04894102 1.8265452 -0.10863401 0.70622677 1.3305945 -0.6371118 -0.25508776 -0.7116915 -0.1621196 0.028408915 -0.5515177 -0.4256775 -0.119045004 -0.0028868755 1.7047099 0.65529007 0.290463 0.2645048 1.1118442 0.08760529 0.35812777 0.6402641 -0.19340418 0.047335222 -0.25716418 -0.3357477 -0.028790148 -0.6340571 1.9856257 0.46009827 0.8366939 1.2006122 1.772615 0.70024043 2.0800645 0.41881752 1.9341432 1.3697416 0.2151358 -0.37917376 -0.46087041 -0.4330339 -0.3989405 0.38897437 1.7815127 0.87810373 -0.09691813 1.0793978 -0.30144322 -0.1332004 -0.47295305 0.052805353 1.3968022 -0.4405524 0.5615078 0.07214186 0.11452939 -0.43489254 -0.5254758 0.24991584 1.9852307 0.24795821 -0.19427969 -0.78738105 -0.2594365 -0.6366712 -0.059418768 -1.0128697 0.119840816 0.6233335 -0.8563437 0.16562214 -0.15575652 -1.0031153 -0.77282935 0.14595269 -0.15075806 0.69212824 0.385454 0.70164734 -0.21775697 0.1363892 0.69458365 -0.3247153 0.304316 0.40166432 0.61550486 0.4590282 -0.99416476 -0.75351214 -0.19859429 0.63311404 -0.5414229 -0.61928415 -0.33350274 -0.08193817 -0.43711534 1.312692 0.22371696 0.4998732 -1.4381112 -0.45391116 -0.14466119 0.13299882 -0.4398423 -1.0650498 -0.57404834 -0.022888102 0.07370311 0.42288736 -0.12854199 1.6363946 0.48725113 0.1256565 0.132517 2.2078724 1.7647432 0.54534477 -0.29645523 -0.014265128 0.0031991815 -1.1028551 0.20085983 -0.3626875 0.75738674 -0.5516592 0.23809087 1.2856133 0.2602971 0.159506 0.6775368 1.8702489 -0.67913526 0.5872139 -0.049447875 0.1401503 -0.30865434 -0.017763581 0.4212067 -0.5220319 -0.16127284 0.182768 0.22131704 -0.2563105 0.8774896 0.81703246 0.39628422 0.36231348 0.27511787 -0.67843133 0.7222071 -0.3318762 -0.22084595 -0.10715687 0.45792416 -0.69571006 -0.2337643 0.4646986 -0.58650315 -1.257193 0.32932052 0.69814795 0.60938543 -0.0033802344 0.57839423 -0.72781754 -0.44834042 1.2148023 -0.45138305 -0.44424665 0.002405336 
+0.324198 1.0461272 1.2694957 0.4512405 -0.2652417 0.3910717 0.44935483 -0.21196514 0.2629787 -0.1512267 -0.77435136 0.09432993 -1.1581715 -1.3761951 -0.8345308 -0.14183271 0.55220014 1.6007001 2.8263679 1.70961 0.54359204 0.5355011 -0.6789151 -0.03083109 -1.2098876 0.6617001 0.22374049 -1.4273605 -0.73623675 -0.9129155 -1.131973 -0.22065617 0.691493 2.0277522 0.26925856 1.5305483 0.6709371 0.20227751 0.068769686 0.5850261 0.6748788 0.73886716 0.34821013 0.3525081 -0.07495136 0.85512173 0.39809817 -0.10609535 1.5158496 1.0238556 -0.8108836 0.46903142 1.601046 1.726886 0.34955332 -0.016258225 -0.5941145 -0.023201821 0.55685717 0.26252788 0.8420125 0.424427 0.6617056 0.08824403 0.5074534 -0.5294419 -0.14202312 0.49772465 -0.14377417 0.48481622 1.0671204 0.6021328 0.73497283 1.2793562 1.8897928 1.4676578 -0.0028625797 0.6925298 0.46102804 -0.34925345 1.0688409 0.16698326 0.048282154 0.540996 -0.30838716 0.7248276 0.29081362 0.972803 0.44625488 0.9584397 -0.11455195 0.76300156 -0.2870343 -0.02156472 -0.7065148 -0.8122646 -1.8752956 -1.0862988 -0.45103583 0.6903231 0.29875067 0.49932885 0.4794718 0.24442543 -0.0068962984 1.0294654 -0.7357702 -0.8991665 0.26515794 -0.4879827 -0.47417215 -0.19405249 -1.5863919 -1.4758667 -0.54633105 0.18324628 0.4633917 -0.033322446 0.39619434 0.42733702 0.122756906 0.02227159 -1.0575666 -0.62055826 0.49268726 -0.7136375 -0.095852174 0.5549872 -0.8536564 -2.178404 -0.300334 0.047558192 -0.3964429 0.32078004 1.0711937 0.55719215 0.813753 0.5281706 -0.232745 0.66162264 -0.78145444 -1.0273473 -0.10876257 -0.29961237 -1.4574498 -0.87940794 0.8429038 -1.0321039 -0.708817 -0.19679457 0.118829854 1.0844388 1.0192103 0.97893524 -0.995705 -0.42097467 -0.37923548 -0.8797356 -1.295534 -0.3051011 -0.8584191 -0.6237388 0.29994914 -1.3988845 -1.3279945 -0.49047482 0.32205492 1.3268211 1.1962954 -0.6294789 -0.38372847 -0.85408545 -0.73402506 -0.20355508 0.22647385 -0.07613414 -0.28519404 1.1703242 -0.45440575 -0.4135681 -0.34366113 -1.4143696 1.00077 0.24402937 1.4169945 0.4381622 -0.50034785 -1.2099575 0.08010042 -0.22207321 0.691786 0.8651564 0.5949732 -0.54578954 0.2988547 -0.70302564 -0.09706479 -0.84604925 -0.61748755 -0.47333083 -0.76055634 -0.89320695 -0.81461495 -0.4408807 -1.5906909 -1.3327279 -0.06900973 0.5701455 0.19715816 0.31585297 0.094794475 -0.8327079 -1.5525787 -1.5317106 -0.7430849 -0.09764588 -1.4631271 -0.63548887 -0.30477706 0.6044156 0.48830822 0.3792617 0.13980179 0.35247844 0.5683721 0.2620647 0.065488145 0.67121565 -1.4460824 -1.1892319 -1.1609538 -1.6012245 -0.48742616 -0.73144174 -0.80351233 -1.1037393 -0.4560784 1.2434199 1.052172 0.71905494 0.26975644 0.09405528 0.4352493 -0.34652016 -0.30116236 -0.53785765 -0.91251385 0.28221196 -0.92031467 -0.38684094 -1.4538802 -0.4093127 -1.0508169 1.2602098 0.016090408 -0.7781259 0.0038164053 
+0.34899452 0.43551138 -0.1801633 -0.13980372 -0.5918415 0.18512389 -0.637774 0.026483025 -0.9288965 2.018797 0.46602428 1.1350625 0.41534 0.6509708 0.08684477 -0.04923758 0.8290408 1.3959218 0.6300726 0.5571067 0.8959025 -0.22214186 0.64646083 2.8538108 1.8655826 1.3476434 3.0967402 2.3441684 2.1149242 0.85789347 0.19943236 0.39221576 0.38796857 0.9733669 0.08322598 -0.5326969 -0.8128047 0.37836513 -0.89841354 -0.67026436 0.29363325 -0.67997354 -0.74180055 -0.058875903 -0.06250465 -0.92607105 -1.0153372 -0.0969821 0.25615576 0.40146148 -0.54210913 -1.6560907 -1.3732036 -2.8062165 -0.9654973 -0.49074185 -1.4813517 -1.6107234 -1.3373486 -0.29287192 -1.365529 -0.24954084 -0.47448388 0.16028914 0.013301278 -0.48837075 -0.4094247 -1.032309 -0.90245533 -1.03609 -1.9138631 -0.4753778 -1.6546791 -2.2272875 -1.4139003 -1.4760089 -0.15532427 -1.7432575 -1.3446383 -0.51282495 -0.95714754 -0.43583247 -1.334729 -2.2898617 -0.8643527 -0.7869274 0.31103888 0.5299115 -0.44906798 0.57519144 -1.3482019 -0.79081005 -0.38887706 -0.99623656 -1.2482314 -0.5375696 -0.37459093 -1.433549 -0.726984 -0.46087775 0.5163761 0.7579098 -0.0470452 -0.43948933 -0.1816129 -0.19911431 -0.82070637 0.041347876 -1.1635152 -0.72388643 -0.88093144 -1.1555365 -0.5438338 -0.824328 -1.342995 -1.0908883 1.3741925 -1.7666208 -0.82256263 0.358632 0.60077715 -0.8494634 -1.1399274 0.1382732 -0.91434336 0.084631145 -0.8233162 -1.2037952 -1.1061074 -0.28464884 -0.04643375 -0.19073112 -0.36857077 0.12336258 0.44430372 0.6439594 0.059810374 0.6096434 -0.70409495 -0.3088769 0.33569968 -0.37674662 -1.3242744 -0.7852339 -0.35477704 0.16999471 -0.3471375 -0.5710284 -0.49106717 -1.6561658 -0.7034081 -0.6409242 1.0552794 -0.37279034 0.35563794 -0.03772467 -0.37208197 0.060365204 -0.82755774 -0.7269516 -0.4857834 0.043305416 -0.36041072 -0.23812898 -0.77312165 0.45424488 -0.10475901 0.02657198 -0.61215305 0.014454754 -0.9827011 -0.9867617 -0.68099046 -0.17517185 -0.050069038 -0.18135889 -0.08887155 0.41666672 0.36290786 -0.81357694 -0.88243884 -0.6983182 -0.5859458 -0.82072574 -1.3786892 -0.6161044 -1.3181741 -1.154877 0.18651165 -0.60539466 -0.42235956 0.13513772 0.04606362 0.24692588 0.063127846 0.5655238 -0.50693476 1.5995939 -1.2209054 0.2774633 0.14298461 0.4657873 -0.52006763 -0.6703785 -1.5149626 -0.8586979 -0.119561225 0.61693907 0.21801832 0.22349398 0.9523007 -0.077727735 -0.6596435 0.37848318 1.5563408 0.22579147 1.0999234 -0.22044803 -0.004981784 -1.077948 -0.93620175 -0.50398755 -0.95377624 0.54068756 0.76723456 0.019627063 1.1717428 0.08105768 1.5366242 0.93099356 0.41787595 2.5288703 1.6796426 1.1964376 0.0832777 0.85741264 -0.544418 0.14558968 0.048237406 0.054582797 0.22259393 0.4035469 -0.1483494 -0.07487902 -0.8609459 0.58568764 0.9888189 1.4579424 0.7116446 0.85291827 -0.20448285 -0.40498826 0.5194304 -0.39215624 0.37348232 -0.11054524 0.025268624 
+0.31355312 -0.2569207 -0.44129074 -0.32759556 -0.15829423 0.105932645 0.6399394 1.599404 0.40299812 -0.16353549 0.5335733 -0.632891 -0.24842605 1.0833986 0.41112247 0.6617023 -0.599724 -0.9514725 -0.37196353 0.3283547 0.5355613 1.4060141 1.2545475 1.0404451 0.11272732 0.13567385 0.07742863 -0.26108146 -0.67378247 -0.0870784 1.598958 1.1734076 0.103656664 0.7154092 0.35276014 1.160704 0.5682231 0.15320581 0.50946033 1.0670927 -0.6342676 -0.81340474 0.97553885 -0.62385046 -1.4823159 1.1215645 0.7644669 1.245594 -0.6637506 -0.90373206 0.54475504 0.023331244 -0.13945916 -0.52110726 -0.62472475 -0.46704677 -0.4924951 -0.71503836 1.1971612 -0.2276264 -1.8007241 0.13122723 -0.1153043 1.2140326 -0.47213677 -0.8009326 -0.2873047 -0.7838971 -0.63734716 0.26143286 0.10977667 -0.071351275 0.5698748 0.014942971 -1.4033812 -0.6306406 -0.5739755 -0.23926045 0.3807677 0.116832286 -0.96081847 -0.56976724 0.3841466 -1.4820241 -0.8008879 1.1997848 0.27921215 1.0320961 1.043212 0.51919836 -0.42857763 0.026702838 0.23546018 -0.4276841 0.11047624 0.47510648 -0.16051751 -1.1061442 -1.3156124 -0.24219395 0.3003598 0.7345225 0.77221596 2.6825595 0.9272541 0.52901965 0.17974725 0.7089881 -0.36509198 0.45378944 0.5697395 -0.7221791 -1.8710384 -1.5365134 -0.892935 -0.4457689 0.8233435 0.087499045 1.6807845 1.0369619 -1.0247252 0.94427013 -0.11924478 -0.1819553 0.13903317 0.3666592 -0.24962665 -0.83833146 -1.7741002 -2.2587268 -0.5419408 -0.5958509 -0.7266291 0.8095073 1.6498561 0.9073211 0.8720946 -0.018906552 0.32695666 0.3393011 -0.37780795 0.22121322 -0.11927222 -0.510951 -1.980878 -2.6377234 -1.367223 -1.3971337 -0.24230005 0.22565581 0.5059276 1.6443602 -0.066822946 0.50422305 -0.40116 -0.0072107436 0.9827137 0.6210337 0.255268 -0.48262388 -1.8033098 -2.4241772 -0.52113265 -0.59755844 -0.47868744 0.5800802 1.4724234 0.8924181 1.0393144 0.31674403 -0.16051611 0.63050085 2.013169 0.43357188 0.035331856 -0.45989114 -0.9146474 -1.3458794 -1.8940005 -0.23117502 -0.5375885 0.123129144 0.92206466 0.8587084 0.66943973 -0.2759229 -0.9128281 1.1141527 0.7866131 -0.02197686 0.7536428 -0.10551563 -0.50085837 -0.56148833 -0.32149318 0.2190853 0.17272301 0.31370527 -0.53203875 1.0979165 0.3691644 1.1545193 -0.36878273 -0.09787914 0.9670017 -0.08824843 0.19481541 0.32729 -0.67850226 -0.0077991383 0.29042608 0.1008822 -0.41987768 0.088948674 0.10741654 -0.06070189 -1.0778598 0.039762326 -0.8064945 0.73079884 -0.68271154 0.032141402 0.35474864 -1.4368619 0.4057375 0.18610571 -0.3733003 0.78862125 0.7269798 0.3222252 -0.8543098 -1.316651 0.38973936 -0.019797457 -0.95832705 -0.37404072 -0.26126316 -0.8943949 -1.4501934 -1.1539205 0.13762718 0.07294907 0.53397864 0.373358 0.2633841 0.06297146 -0.49937835 0.28753504 -0.64221865 -0.3434134 1.1786649 -0.9444955 -1.0259506 -1.1684353 -1.0433656 -0.92095876 0.02317189 
+0.49883622 0.8738015 0.07538438 -0.53190774 -0.8169132 -0.4654301 -0.75953823 0.61147225 0.55531156 0.7574796 1.0460283 -0.46929035 -0.039527465 0.89011025 0.0029253045 0.046302635 0.60812104 0.10492641 -0.8656824 0.60333836 0.7821837 0.18454382 -0.1711819 2.8021684 2.0009508 1.243945 -2.4809805E-4 1.1659219 -0.3866369 1.3590945 1.8321466 0.17325824 0.7315904 1.0736189 0.55457634 0.58655006 0.6639926 0.5549225 0.8504128 0.86628324 0.41518113 1.0283749 0.42744657 1.1177511 0.7092364 0.48287052 0.5519719 0.6621105 0.8691472 0.68850785 -0.33879724 -0.31775013 0.8507639 -0.3774613 1.0013268 1.5704612 -0.226301 -0.6631143 0.34470502 0.736129 1.0288049 0.41759476 0.3519841 0.04826597 0.9896556 0.502269 0.59868234 1.087104 0.014414474 -0.1628346 0.13342115 0.2699755 -0.72850776 0.5009547 0.6400719 0.43565235 1.7031748 0.6933077 -0.47167856 -0.2367978 0.24320003 0.9809215 0.4564348 0.18173188 0.84841526 -0.37224346 -0.31442142 -0.057412688 -0.34721774 -0.54385746 0.31509566 -0.1115179 -0.360106 1.2927624 0.1583295 0.043638255 1.4400384 0.5007109 0.21775734 -0.622246 1.1702619 1.0436081 0.2725648 -0.21549857 -0.03598858 -0.16443002 -1.1526567 1.8192471 0.33136237 0.83405006 0.23746926 0.4573318 1.6676764 -0.087492935 0.61379576 0.0793459 -0.04422792 -1.1592702 -0.08544064 -0.23945487 0.042512167 0.35734397 -0.8288806 -0.65794015 -0.29728588 0.15713137 0.536605 1.0444872 0.27764803 0.39361793 -0.85221267 -0.76842654 -0.8112615 0.47227907 0.87249994 -0.42854384 0.2784465 -0.19874159 -1.0792364 -0.22735132 0.6576991 0.8266387 -0.78881276 0.13905783 -0.20210706 0.61103046 -0.51635265 -0.3043786 -0.8134132 -1.4495662 -1.271393 -0.20779374 1.3198719 0.2956729 0.459104 -0.1824437 -0.15204583 -0.90568125 -0.37422338 0.43446416 -0.052006707 -0.13453352 0.47284144 0.3424477 0.7878659 -1.29038 -1.1850036 -0.48110694 -0.051368486 -0.8004262 -0.8516914 0.74701405 -0.55217254 -1.4585956 0.2849024 0.3748153 -0.52690715 -0.13875818 0.91924167 -0.60812974 -0.16129309 -0.41176206 0.60509497 0.26093718 -0.09773811 -1.7672535 -1.326208 -0.7874701 -1.130104 -1.0682622 0.05656509 0.25562486 -0.29242155 0.7207595 0.07820444 0.55645066 -1.1481186 -0.4348599 0.47691604 0.61596817 -0.92253006 -1.1836563 -1.5725946 -0.7895914 -0.13117582 -1.2490474 0.027346283 -0.31888416 0.4242007 0.4647982 -0.6039706 -0.86170834 -1.5070595 -0.29471865 0.7806233 -0.30346632 0.82369167 -1.9140621 -1.2397135 -0.5477873 -1.087546 -0.3498546 -0.84286237 0.43365687 0.33316892 0.31791714 -0.35534674 -0.64584637 -1.1461787 -0.53249437 -0.9726551 0.31310228 0.8493431 0.26505184 -1.1402653 -1.6951883 -0.7881438 -0.34877223 -0.56603265 -0.5316156 0.21854547 -0.200699 -0.22073564 0.74820566 -1.3174651 0.44954658 0.48710498 1.5799721 1.0713131 0.54062665 -0.35746223 -1.3621521 -0.8017228 -0.91521835 0.33674014 0.2767572 -0.02616764 
+-0.18537915 -0.98226094 -0.45052698 0.5297868 -0.01609077 0.4291576 0.86536914 1.5901328 1.3896016 0.71268654 0.99405 0.6231499 -0.42216265 -0.1024484 -0.6611997 -0.6285279 -0.5370125 -0.73067737 -1.0556656 0.49071532 -0.3982177 0.30409858 1.925281 3.0892148 3.6179695 2.3695128 1.1990675 -0.56124395 -0.1690238 -0.74463964 -0.88408464 -1.2845768 0.13468586 -0.38228047 -0.6500104 0.2669491 -0.42273104 0.63166416 1.2274182 1.402954 1.7609581 1.0579638 -0.6925936 -0.8886774 -0.33242154 0.078056514 -0.45943132 -1.3518296 -0.75991064 -0.8375209 0.63642204 -0.066176854 -0.3558449 1.5183419 1.7831364 1.763367 0.66410565 -0.046603177 0.29276398 0.0153499 -0.49144736 -1.0273223 0.012938061 -0.46269718 0.83231515 -0.61673874 0.04597479 0.09324714 0.65462494 0.95914596 0.5155392 -0.70423424 -1.774696 -0.16532516 0.16753882 -0.112238616 -1.422655 -1.0354193 -0.45090258 0.10113637 0.3230875 0.7984015 0.57364917 -0.70329285 -1.2432072 -0.7258935 -0.4964063 -2.6535492 -1.3737441 -0.5719242 0.49697337 0.4245664 -1.3735908 0.27821648 -0.06963703 0.682949 1.0315195 -0.9389445 0.16737415 0.0023131468 -0.8528607 -0.23022734 -0.21757695 -0.5087957 -1.5721607 -0.45037323 -0.099977255 0.6938178 0.05377063 -0.5183964 -0.60970247 0.77048725 0.7966707 0.5762057 -0.42235973 0.12370597 0.66862684 0.99824667 -0.026461136 -0.9778955 -0.028188748 -1.944228 -0.69752586 -0.8686891 0.64038384 0.72719777 0.35285038 -0.27627587 -0.5498595 0.88892 0.023587577 1.1860816 0.71524984 0.8106411 -0.4101577 -0.35699233 -1.4711772 -0.31003162 0.7970542 -0.5812901 0.7590856 -0.0938436 -1.1353674 0.07782559 0.66103345 1.1277606 0.3490475 0.80413306 0.6273428 1.2402729 0.19842999 0.47186854 -0.4705327 -0.43522015 -0.07149193 -1.6771804 -0.5813705 0.0112961745 -0.953584 0.04100304 1.4994781 0.45771185 -0.952377 -0.31170908 0.18784817 -0.008882234 -0.42909992 -0.19479105 -0.8323455 -0.53422433 -1.6523142 -0.3984525 -0.20211801 -0.0031169986 -0.6823954 -1.1172303 0.7882518 -0.37490264 0.7321961 -0.3677952 0.7414583 0.7516236 -1.062251 -0.3738374 0.9049916 -0.38614756 -0.016904717 0.35313255 -0.22672379 -0.5068809 -0.4261392 1.0213126 0.9686542 -0.10154391 1.0424329 0.5673016 0.11186445 0.8623114 0.31082287 1.2003645 -0.25093895 -0.28917968 1.6349493 0.19981417 -0.2829063 0.009311169 1.1590991 0.24980175 -0.16430834 -1.4226515 0.92513716 -0.40189648 -0.4083443 -0.21450014 -0.4346813 -0.08093666 -1.2166839 -0.19779441 0.24804594 0.69058484 0.2754155 0.27351496 0.23796122 0.7480597 -0.72054225 -0.73124254 -0.07224956 1.2715003 0.60294753 -0.7234926 -0.5987044 -0.42238608 0.89744955 -0.053801876 0.43394342 0.58834773 1.0219165 -0.58623266 -0.30641058 -0.075494915 -0.40545318 -0.5162443 0.015226424 -0.4084876 -0.1230162 0.22420669 -0.72882015 -0.013819115 -0.21843338 -0.218198 -0.9387914 -0.30078402 1.2397376 -0.37904623 -0.69836 -0.37839484 0.007250318 
+3.3188453 0.40059 -1.9679902 -0.06969836 0.645592 0.8478403 -3.7597065 1.8643434 0.868009 -5.94918 -0.8111086 1.3716624 -1.3318771 -6.057943 -3.4167368 -1.7107545 3.0471072 -6.8019423 -0.5861023 0.6775545 1.8216686 -1.0352285 -2.411754 2.232938 -7.9369297 1.5046302 -3.332253 -3.018245 -2.5044243 -6.877499 0.5581923 4.473815 -0.024825856 
+0.3632732 2.3614464 3.3713956 -5.623532 0.93494517 -1.0177035 0.7173615 -4.96804 -1.6503501 -6.0000777 0.2045284 -5.0006113 -6.1966662 2.0163178 -3.598368 3.9817402 0.5001878 -1.5116302 -0.5121971 -3.8322074 0.89451444 -0.18629399 -2.5604308 0.71212083 0.306262 -1.8034369 0.42934173 -2.145597 -4.502384 1.0959655 -3.1901493 -0.891438 0.0052635614 
+-4.4513197 -1.232425 2.6870427 3.2452874 -1.3963414 1.6518897 -2.8090582 -0.8918251 -4.6075926 -2.5077202 -2.6742818 -0.6963682 0.9420355 -1.6897413 0.99827325 0.04448109 -2.7016869 -3.7606738 -0.94711155 -0.42924723 2.9632182 0.93144786 4.764138 -1.4380913 4.107077 -3.2295914 -2.9563181 -2.8342938 1.9359553 -4.9888434 0.4994436 0.18100053 0.022587147 
+-0.639423 -1.3831495 0.4468618 -0.28865674 -9.775045 2.6633239 0.06268622 1.8427695 -3.4072003 3.9190497 1.0533204 -1.4792175 1.8750358 0.7115673 -3.861028 2.03331 1.6446928 -1.7451559 -2.9372728 -2.8554428 2.783749 -1.178357 -3.765316 -1.1463546 -3.5237794 -1.1172531 -0.8649558 -2.4926033 -4.0221877 -0.57793397 -6.928154 -0.74644136 0.030580435 
+-0.8511717 -1.0888187 0.21832423 3.6264567 -0.72284603 -2.165236 -2.7835886 1.1359786 4.094847 -0.14354818 0.12435902 0.7284857 -0.77557224 2.8904648 -3.0898228 1.6451933 -0.5899573 1.6661206 -3.752382 -3.29638 -0.6516911 -6.2895336 -4.9999743 -4.751674 -3.8747354 -4.665546 -2.5337596 -5.1378093 0.9923492 -9.2668705 2.0741165 2.574558 0.039836783 
+-3.3618622 2.6225154 -6.2883058 0.25442094 -4.1493583 -0.41389433 2.6924343 -1.1820143 -5.618627 1.356849 -5.019766 1.6696825 2.092018 -1.6391217 -5.393632 -2.7981253 1.8893806 -1.9388933 5.1797557 -2.954032 -1.1735597 -3.8161666 -4.4212675 -3.9115098 -3.2309496 6.0728264 0.025871223 -4.6461387 5.3370523 1.0341136 1.2461692 -1.720388 0.024860557 
+-1.2358694 4.1247025 0.08740824 -4.3771353 -0.030969817 1.031388 -3.1342778 0.7090729 0.49605337 -1.6042751 -1.8085297 -9.046925 0.8157869 -3.8854432 -3.3482633 -0.53522027 0.21666339 0.8697372 -7.8332415 -0.5469962 -4.405077 -4.7637396 -4.394621 -5.994705 -5.418705 -4.145933 -1.8615875 -3.1843278 -2.735348 3.6834736 3.6490235 4.945123 -0.020013118 
+1.8197824 -2.8312726 -1.6365352 -2.9895499 1.6129265 3.4348679 -1.8052833 -1.5420055 -4.8966184 -4.6325965 -0.061136648 2.165334 2.1105518 1.6097159 -0.31565392 -9.934366 2.260088 -2.6938198 -1.3954766 -0.7070942 -1.1792121 -2.2252917 -0.10980059 -0.11566961 2.7799675 1.0673789 4.6228166 -2.2967038 -1.3443925 1.2742109 -4.1370153 -0.63993543 -0.024386141 
+-0.7715497 -2.3300824 -1.8012121 4.8299856 -3.2595117 4.664556 -1.9699382 -7.3050585 -0.5722891 1.8220688 -2.5350072 -2.4604144 0.092435844 0.53040916 2.7670844 -3.0026073 -10.599527 1.0140266 1.9128901 -0.29929286 1.8670084 1.8597156 1.8260541 1.6761122 -0.09393797 -2.0504067 4.558832 2.234363 3.7772114 2.0039213 -0.6626459 -1.574328 -0.0040445877 
+1.8952433 1.8856168 1.1119277 -4.4144793 -4.7854204 -2.56885 -1.6020781 -0.42634428 -1.1362706 1.3833557 -4.02971 -2.8391373 -4.173429 -4.0498304 2.928348 0.46056744 -1.0412822 -3.0846875 -2.8325171 -1.9743062 4.5396714 1.4534146 3.8350468 -0.06542266 -0.48209596 -3.496334 3.4790037 -1.0122944 4.563831 -2.4299686 -4.1514144 -1.9072495 0.019211592 
+0.28322476 -5.1883173 0.122715116 4.0505824 -3.1462262 -6.796414 2.2734184 -4.098528 -0.60894316 -6.54831 4.2180057 0.6621108 1.6274971 2.2397742 -5.5765843 0.6283236 0.7379073 1.7373952 -0.3651221 -5.041317 3.965837 -5.2236643 -2.2686272 -1.9154938 2.6809785 -0.22754136 0.3797499 2.6155822 -0.37388822 -3.9279466 -6.1213164 -3.1557689 0.0030120001 
+-0.8198072 -3.320936 -2.829201 -0.6887955 -0.47655535 -5.633271 5.8044443 1.834403 -4.216584 -2.6752787 -1.0306456 -4.2755737 -6.588805 -1.0150422 1.7686261 -0.3829343 2.1872528 -3.4612815 3.4437048 -2.207867 0.1888097 0.49778536 5.7171288 0.32646227 -1.2284694 0.51398253 -10.336291 2.114793 6.6587143 -1.5447686 -2.3190935 1.8876063 -0.047436677 
+-0.62963194 1.4777945 -1.7571894 -2.6769009 0.39057454 -3.7364814 -0.8392782 -2.3699584 0.09312773 1.8219194 2.7355092 1.7888372 -0.81204736 -2.935253 -2.1590881 -1.5556968 -4.610923 1.9892942 2.3136575 3.2912333 -4.83361 -4.248878 -1.400305 -2.403121 -4.0466743 -0.08205262 -1.2859818 3.1537158 -1.861443 -5.811996 0.458375 -4.027502 -0.02590746 
+-7.615588 1.3614897 1.4939482 -5.205575 -1.673643 0.74357635 -2.7372591 1.6170616 2.435418 -3.4419708 -0.06518204 1.2442499 1.1266783 1.3549963 -0.9004273 -5.7754664 -2.624869 -1.6468443 1.0941269 0.7589392 -5.706259 2.6252341 -2.405118 -2.4348783 3.6782053 3.306361 -3.2466447 -1.553077 -2.5804696 1.0159948 -2.3408878 -1.8535192 -0.0021200308 
+-4.013827 0.2610515 2.111559 -6.3211656 -2.1001635 1.9053426 -1.6727843 -0.44091293 -0.76261014 -1.0390077 -1.7525955 -2.720178 -2.529168 -5.6742926 2.6151636 0.51420337 0.71321785 4.3812776 3.1439812 0.77312356 -2.8765817 1.9708476 -0.86634195 -2.2173822 0.38174078 -4.7265043 -2.6250343 -3.9365456 -1.9344738 -4.6156936 -0.7695132 1.912843 0.011368353 
+-7.697162 -0.26664928 -6.4262285 0.72342825 -4.9268126 -3.5221684 -3.8728328 -3.2982187 1.3733284 -5.8051333 1.4574023 -0.96571344 0.58893365 -3.181542 3.262099 1.6309257 -1.5365862 2.3387916 -5.255009 -0.10661021 -2.132601 -3.5527897 2.3372629 -3.7519357 -1.9273626 3.992388 -5.48636 0.6817621 -2.9058044 -1.9674861 4.4054747 3.334584 0.007431256 
+-1.6424383 -5.8564734 -1.8093833 -3.715056 1.3547465 -1.2179599 -5.499006 2.3751373 0.4895267 2.7063863 -6.2402163 7.3155036 -3.6011443 -2.7977996 -4.6695447 -2.862364 0.75960207 2.9870906 2.8959186 -5.650074 0.539843 -4.619602 -2.5695598 -0.467896 -3.390343 -2.4309294 -2.590085 3.249129 -5.5731363 1.9717381 0.26087123 0.67754215 -0.045831084 
+-1.7940446 -1.3843921 -4.6716633 4.1857424 -0.50761205 -3.6805487 1.9576495 -3.053029 -5.650654 -0.72363085 -0.4052815 -0.891051 -2.4934862 2.1326828 4.351335 -4.7457786 -0.87060124 1.9086488 0.39036214 4.53587 -5.013919 4.2015347 -1.5139904 -1.8883435 4.1603584 -2.70182 -0.36223388 1.7974008 1.2901081 -0.37577942 0.0105882725 -4.2853737 -0.01637644 
+-1.5830569 -0.7317656 2.4023943 -2.004526 1.2185715 -0.55593747 -3.4697645 -6.1193686 -1.7822918 1.5736116 -2.7630713 3.676887 1.0927823 -1.3736699 -4.150244 0.2997286 1.5663744 -3.378952 -1.3276973 0.24779214 -5.9093213 1.0596575 0.50607246 4.050893 -4.0679774 -5.162828 -1.8389171 -4.4217887 1.7034249 3.731301 -2.2410748 -0.7650962 -0.016503714 
+3.5579996 -2.51934 4.575838 7.258866 -4.859554 -1.3860203 1.3648074 2.2165234 4.1006 -3.2093186 -4.469197 -4.7680097 -0.6160599 -0.62733936 1.571316 -5.516408 -2.6344726 -0.36233923 1.2449152 -2.4668746 -8.253659 1.8876019 4.7397947 -4.1485906 -0.40496337 0.9102521 5.0837426 1.9607608 -4.3280587 -0.7465847 -3.9982235 -1.049976 0.041746177 
+2.4787107 -2.440761 -1.4641386 -2.9584825 1.8319176 2.6269035 -7.5023637 1.8800472 -0.64747334 2.6456115 1.113191 -2.2647874 0.39089805 -3.2810428 -1.1749662 0.18277311 -5.4791713 -2.1531775 -1.6886452 2.1894584 3.0858085 2.0088425 -3.1921341 -2.1513703 7.11089 -1.8595059 -1.14462 0.7134691 -2.9010673 -2.1420977 -4.555495 -5.8109202 -0.0020564618 
+1.7578679 -2.3976014 1.5388082 -2.8396344 -0.17281288 -5.439047 3.2236662 -1.862213 -4.4158125 0.08120502 -4.8469143 1.0403296 -0.57074785 -0.8282122 4.5666046 -0.057304364 -5.511647 1.7642924 -2.6845326 0.25282356 5.579816 1.5881189 -3.7861753 -3.7130008 5.0709996 1.1625888 2.1444614 -0.0748934 -2.7709198 -1.1461511 2.6962454 -3.866843 -0.01615078 
+-1.3438528 0.6370322 -5.153015 -1.706669 -1.5238507 -1.461546 3.4800727 3.378386 0.21473399 1.3823695 1.2987071 -3.2407484 -6.6887445 3.9367244 -4.3351197 -1.388976 -1.423658 2.1621523 1.1173093 2.1123621 -0.18855162 -2.5684676 -1.3163676 1.7352618 -3.5005045 -1.4386475 -1.4427011 -6.3370504 -2.3031182 -0.64208794 -1.9835476 -2.4418921 0.01610778 
+-3.1874948 -2.3977308 -2.702749 -1.1587065 -1.0463094 -1.710468 0.033704665 0.3566389 -0.76097363 1.7152604 0.3606053 -0.44375435 1.4578848 -0.61850345 -5.278605 -2.339693 -0.8100282 -3.6413932 -4.3556676 5.3163548 -6.138357 0.7554096 -0.3293253 7.2791667 -2.2634993 -1.4381553 -5.0166793 3.4261372 -2.924105 2.9263134 -2.9614942 -4.837568 0.04072551 
+3.7139666 0.19742009 2.0511174 -1.384915 0.016993588 -4.7682934 0.6759354 -4.224599 -1.8024838 0.7470361 4.309398 -0.46020854 -4.684363 -3.2771602 4.121208 2.430816 0.93080497 -5.46639 -5.5941343 -2.4674442 -5.472979 -0.32386532 3.2534885 -6.1389556 -2.179047 1.4061046 -3.4079444 2.4176822 -4.659507 2.3622673 -0.5147894 -5.554515 0.0031532426 
+-0.9338535 -8.511058 -2.4692512 -0.89263976 2.3165276 1.7393429 -2.2559807 -0.43257144 2.4999452 -0.1843885 0.49021253 -4.820904 -1.1133385 0.09079128 1.7847239 -1.9373181 -0.8417471 -5.1364603 1.234991 1.8285574 1.554807 2.6041527 -1.9148797 -4.530061 -4.047518 -2.2234762 -3.6861074 2.988775 6.2937946 0.9297057 -1.7499388 2.496612 -0.0090153795 
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 7db73f0..eb94812 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -110,7 +110,10 @@
         <item><xliff:g id="id">alarm_clock</xliff:g></item>
         <item><xliff:g id="id">battery</xliff:g></item>
         <item><xliff:g id="id">phone_signal</xliff:g></item>
+        <item><xliff:g id="id">phone_evdo_signal</xliff:g></item>
         <item><xliff:g id="id">data_connection</xliff:g></item>
+        <item><xliff:g id="id">cdma_eri</xliff:g></item>
+        <item><xliff:g id="id">tty</xliff:g></item>
         <item><xliff:g id="id">volume</xliff:g></item>
         <item><xliff:g id="id">mute</xliff:g></item>
         <item><xliff:g id="id">speakerphone</xliff:g></item>
diff --git a/core/res/res/xml/eri.xml b/core/res/res/xml/eri.xml
new file mode 100644
index 0000000..cd66f14
--- /dev/null
+++ b/core/res/res/xml/eri.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<!-- Note that IconMode can be only 0, ON or 1, FLASHING
+     The icon is turned OFF if then IconIndex = 1 -->
+
+<EriFile VersionNumber="1357"
+         NumberOfEriEntries="12"
+         EriFileType="1">
+
+         <CallPromptId Id="0"
+                       CallPromptText="CallPromptId0"/>
+
+         <CallPromptId Id="1"
+                       CallPromptText="CallPromptId1"/>
+
+         <CallPromptId Id="2"
+                       CallPromptText="CallPromptId2"/>
+
+         <EriInfo RoamingIndicator="64"
+                  IconIndex="1"
+                  IconMode="0"
+                  EriText="T-CDMA 64"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="65"
+                  IconIndex="65"
+                  IconMode="0"
+                  EriText="T-CDMA 65"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="66"
+                  IconIndex="1"
+                  IconMode="0"
+                  EriText="T-CDMA Ext 66"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="67"
+                  IconIndex="67"
+                  IconMode="0"
+                  EriText="T-CDMA Ext 67"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="68"
+                  IconIndex="68"
+                  IconMode="0"
+                  EriText="T-CDMA Roam 68"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="69"
+                  IconIndex="69"
+                  IconMode="1"
+                  EriText="T-CDMA Ext 69"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="70"
+                  IconIndex="70"
+                  IconMode="1"
+                  EriText="T-CDMA Roam 70"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="71"
+                  IconIndex="1"
+                  IconMode="0"
+                  EriText="T-CDMA Ext 71"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="72"
+                  IconIndex="72"
+                  IconMode="0"
+                  EriText="T-CDMA Ext 72"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="73"
+                  IconIndex="73"
+                  IconMode="0"
+                  EriText="T-CDMA Roam 73"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="74"
+                  IconIndex="74"
+                  IconMode="1"
+                  EriText="T-CDMA Ext 74"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+         <EriInfo RoamingIndicator="75"
+                  IconIndex="75"
+                  IconMode="1"
+                  EriText="T-CDMA Roam 75"
+                  CallPromptId="0"
+                  AlertId="0"/>
+
+</EriFile>
diff --git a/docs/html/guide/tutorials/hello-world.jd b/docs/html/guide/tutorials/hello-world.jd
index 4d1e9cd..79b723d 100644
--- a/docs/html/guide/tutorials/hello-world.jd
+++ b/docs/html/guide/tutorials/hello-world.jd
@@ -29,7 +29,7 @@
 
 <p>Before you start, you should already have the very latest SDK installed, and if you're using
 Eclipse, you should have installed the ADT plugin as well. If you have not installed these, see 
-<a href="{@docRoot}sdk/1.1_r1/installing.html">Installing the Android SDK</a> and return
+<a href="{@docRoot}sdk/{@sdkCurrent}/installing.html">Installing the Android SDK</a> and return
 here when you've completed the installation.</p>
 
 <h2 id="avd">Create an AVD</h2>
@@ -80,7 +80,7 @@
       "Android XML File" will also be available.)</p>
     </li>
 
-    <li>Selected "Android Project" and click <strong>Next</strong>.
+    <li>Select "Android Project" and click <strong>Next</strong>.<br/>
       <a href="images/hello_world_0.png"><img src="images/hello_world_0.png" style="height:230px" alt="" /></a>
     </li>
 
@@ -147,7 +147,7 @@
         built against the 1.1 platform library will run normally on the 1.5 platform. The reverse
         is not true.</p>
     </li>
-</ul>
+</ol>
 
 <p>Your Android project is now ready. It should be visible in the Package
 Explorer on the left.
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index a3c702f..1471435 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2900,8 +2900,13 @@
             int N = packageActivities.size();
             ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
                 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
+
+            ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
             for (int i = 0; i < N; ++i) {
-                listCut.add(packageActivities.get(i).intents);
+                intentFilters = packageActivities.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    listCut.add(intentFilters);
+                }
             }
             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
         }
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index fa54421..88f47fd 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -26,6 +26,7 @@
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -39,48 +40,64 @@
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.DefaultPhoneNotifier;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneStateIntentReceiver;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.server.am.BatteryStatsService;
 
-
 /**
- * Since phone process can be restarted, this class provides a centralized
- * place that applications can register and be called back from.
+ * Since phone process can be restarted, this class provides a centralized place
+ * that applications can register and be called back from.
  */
 class TelephonyRegistry extends ITelephonyRegistry.Stub {
     private static final String TAG = "TelephonyRegistry";
 
     private static class Record {
         String pkgForDebug;
+
         IBinder binder;
+
         IPhoneStateListener callback;
+
         int events;
     }
 
     private final Context mContext;
+
     private final ArrayList<Record> mRecords = new ArrayList();
+
     private final IBatteryStats mBatteryStats;
 
     private int mCallState = TelephonyManager.CALL_STATE_IDLE;
+
     private String mCallIncomingNumber = "";
+
     private ServiceState mServiceState = new ServiceState();
-    private int mSignalStrength = -1;
+
+    private SignalStrength mSignalStrength = new SignalStrength();
+
     private boolean mMessageWaiting = false;
+
     private boolean mCallForwarding = false;
+
     private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
+
     private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
+
     private boolean mDataConnectionPossible = false;
+
     private String mDataConnectionReason = "";
+
     private String mDataConnectionApn = "";
+
     private String mDataConnectionInterfaceName = "";
+
     private Bundle mCellLocation = new Bundle();
 
-    // we keep a copy of all of the sate so we can send it out when folks register for it
+    // we keep a copy of all of the state so we can send it out when folks
+    // register for it
     //
-    // In these calls we call with the lock held.  This is safe becasuse remote
-    // calls go through a oneway interface and local calls going through a handler before
-    // they get to app code.
+    // In these calls we call with the lock held. This is safe becasuse remote
+    // calls go through a oneway interface and local calls going through a
+    // handler before they get to app code.
 
     TelephonyRegistry(Context context) {
         CellLocation.getEmpty().fillInNotifierBundle(mCellLocation);
@@ -90,13 +107,18 @@
 
     public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
             boolean notifyNow) {
-        //Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events));
+        // Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
+        // Integer.toHexString(events));
         if (events != 0) {
             // check permissions
             if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
-                mContext.enforceCallingOrSelfPermission(
-                        android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-
+                // ACCESS_FINE_LOCATION implies ACCESS_COARSE_LOCATION
+                if (mContext.checkCallingPermission(
+                        android.Manifest.permission.ACCESS_FINE_LOCATION)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    mContext.enforceCallingOrSelfPermission(
+                            android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
+                }
             }
 
             synchronized (mRecords) {
@@ -105,7 +127,7 @@
                 find_and_add: {
                     IBinder b = callback.asBinder();
                     final int N = mRecords.size();
-                    for (int i=0; i<N; i++) {
+                    for (int i = 0; i < N; i++) {
                         r = mRecords.get(i);
                         if (b == r.binder) {
                             break find_and_add;
@@ -125,7 +147,9 @@
                     }
                     if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
                         try {
-                            r.callback.onSignalStrengthChanged(mSignalStrength);
+                            int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
+                            r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+                                    : gsmSignalStrength));
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -168,6 +192,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+                        try {
+                            r.callback.onSignalStrengthsChanged(mSignalStrength);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                 }
             }
         } else {
@@ -177,8 +208,8 @@
 
     private void remove(IBinder binder) {
         synchronized (mRecords) {
-            final int N = mRecords.size();
-            for (int i=0; i<N; i++) {
+            final int recordCount = mRecords.size();
+            for (int i = 0; i < recordCount; i++) {
                 if (mRecords.get(i).binder == binder) {
                     mRecords.remove(i);
                     return;
@@ -194,8 +225,7 @@
         synchronized (mRecords) {
             mCallState = state;
             mCallIncomingNumber = incomingNumber;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
                 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
                     try {
@@ -212,11 +242,10 @@
     public void notifyServiceState(ServiceState state) {
         if (!checkPhoneStatePermission("notifyServiceState()")) {
             return;
-        }      
+        }
         synchronized (mRecords) {
             mServiceState = state;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
                 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
                     sendServiceState(r, state);
@@ -226,35 +255,38 @@
         broadcastServiceStateChanged(state);
     }
 
-    public void notifySignalStrength(int signalStrengthASU) {
+    public void notifySignalStrength(SignalStrength signalStrength) {
         if (!checkPhoneStatePermission("notifySignalStrength()")) {
             return;
-        }      
+        }
         synchronized (mRecords) {
-            mSignalStrength = signalStrengthASU;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            mSignalStrength = signalStrength;
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
+                if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+                    sendSignalStrength(r, signalStrength);
+                }
                 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
                     try {
-                        r.callback.onSignalStrengthChanged(signalStrengthASU);
+                        int gsmSignalStrength = signalStrength.getGsmSignalStrength();
+                        r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+                                : gsmSignalStrength));
                     } catch (RemoteException ex) {
                         remove(r.binder);
                     }
                 }
             }
         }
-        broadcastSignalStrengthChanged(signalStrengthASU);
+        broadcastSignalStrengthChanged(signalStrength);
     }
 
     public void notifyMessageWaitingChanged(boolean mwi) {
         if (!checkPhoneStatePermission("notifyMessageWaitingChanged()")) {
             return;
-        }      
+        }
         synchronized (mRecords) {
             mMessageWaiting = mwi;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
                 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
                     try {
@@ -270,11 +302,10 @@
     public void notifyCallForwardingChanged(boolean cfi) {
         if (!checkPhoneStatePermission("notifyCallForwardingChanged()")) {
             return;
-        }   
+        }
         synchronized (mRecords) {
             mCallForwarding = cfi;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
                 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
                     try {
@@ -290,11 +321,10 @@
     public void notifyDataActivity(int state) {
         if (!checkPhoneStatePermission("notifyDataActivity()")) {
             return;
-        }   
+        }
         synchronized (mRecords) {
             mDataActivity = state;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
                 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
                     try {
@@ -307,19 +337,18 @@
         }
     }
 
-    public void notifyDataConnection(int state, boolean isDataConnectivityPissible,
-            String reason, String apn, String interfaceName) {
+    public void notifyDataConnection(int state, boolean isDataConnectivityPossible, String reason,
+            String apn, String interfaceName) {
         if (!checkPhoneStatePermission("notifyDataConnection()")) {
             return;
-        }   
+        }
         synchronized (mRecords) {
             mDataConnectionState = state;
-            mDataConnectionPossible = isDataConnectivityPissible;
+            mDataConnectionPossible = isDataConnectivityPossible;
             mDataConnectionReason = reason;
             mDataConnectionApn = apn;
             mDataConnectionInterfaceName = interfaceName;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
                 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
                     try {
@@ -330,17 +359,17 @@
                 }
             }
         }
-        broadcastDataConnectionStateChanged(state, isDataConnectivityPissible,
-                reason, apn, interfaceName);
+        broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
+                interfaceName);
     }
 
     public void notifyDataConnectionFailed(String reason) {
         if (!checkPhoneStatePermission("notifyDataConnectionFailed()")) {
             return;
-        }   
+        }
         /*
          * This is commented out because there is on onDataConnectionFailed callback
-         * on PhoneStateListener.  There should be.
+         * on PhoneStateListener. There should be
         synchronized (mRecords) {
             mDataConnectionFailedReason = reason;
             final int N = mRecords.size();
@@ -358,11 +387,10 @@
     public void notifyCellLocation(Bundle cellLocation) {
         if (!checkPhoneStatePermission("notifyCellLocation()")) {
             return;
-        } 
+        }
         synchronized (mRecords) {
             mCellLocation = cellLocation;
-            final int N = mRecords.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
                 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
                     sendCellLocation(r, cellLocation);
@@ -371,12 +399,10 @@
         }
     }
 
-    //
-    // the new callback broadcasting
-    //
-    // copy the service state object so they can't mess it up in the local calls
-    // 
-    public void sendServiceState(Record r, ServiceState state) {
+    /**
+     * Copy the service state object so they can't mess it up in the local calls
+     */
+    private void sendServiceState(Record r, ServiceState state) {
         try {
             r.callback.onServiceStateChanged(new ServiceState(state));
         } catch (RemoteException ex) {
@@ -384,7 +410,7 @@
         }
     }
 
-    public void sendCellLocation(Record r, Bundle cellLocation) {
+    private void sendCellLocation(Record r, Bundle cellLocation) {
         try {
             r.callback.onCellLocationChanged(new Bundle(cellLocation));
         } catch (RemoteException ex) {
@@ -392,18 +418,24 @@
         }
     }
 
+    private void sendSignalStrength(Record r, SignalStrength signalStrength) {
+        try {
+            r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
+        } catch (RemoteException ex) {
+            remove(r.binder);
+        }
+    }
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
             pw.println("Permission Denial: can't dump telephony.registry from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
             return;
         }
         synchronized (mRecords) {
-            final int N = mRecords.size();
+            final int recordCount = mRecords.size();
             pw.println("last known state:");
             pw.println("  mCallState=" + mCallState);
             pw.println("  mCallIncomingNumber=" + mCallIncomingNumber);
@@ -418,15 +450,14 @@
             pw.println("  mDataConnectionApn=" + mDataConnectionApn);
             pw.println("  mDataConnectionInterfaceName=" + mDataConnectionInterfaceName);
             pw.println("  mCellLocation=" + mCellLocation);
-            pw.println("registrations: count=" + N);
-            for (int i=0; i<N; i++) {
+            pw.println("registrations: count=" + recordCount);
+            for (int i = 0; i < recordCount; i++) {
                 Record r = mRecords.get(i);
                 pw.println("  " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
             }
         }
     }
 
-    
     //
     // the legacy intent broadcasting
     //
@@ -439,17 +470,20 @@
         mContext.sendStickyBroadcast(intent);
     }
 
-    private void broadcastSignalStrengthChanged(int asu) {
+    private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
         long ident = Binder.clearCallingIdentity();
         try {
-            mBatteryStats.notePhoneSignalStrength(asu);
+            mBatteryStats.notePhoneSignalStrength(signalStrength);
         } catch (RemoteException e) {
+            /* The remote entity disappeared, we can safely ignore the exception. */
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
-        
+
         Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
-        intent.putExtra(PhoneStateIntentReceiver.INTENT_KEY_ASU, asu);
+        Bundle data = new Bundle();
+        signalStrength.fillInNotifierBundle(data);
+        intent.putExtras(data);
         mContext.sendStickyBroadcast(intent);
     }
 
@@ -462,13 +496,13 @@
                 mBatteryStats.notePhoneOn();
             }
         } catch (RemoteException e) {
+            /* The remote entity disappeared, we can safely ignore the exception. */
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
-        
+
         Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
-        intent.putExtra(Phone.STATE_KEY,
-                DefaultPhoneNotifier.convertCallState(state).toString());
+        intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
         if (!TextUtils.isEmpty(incomingNumber)) {
             intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
         }
@@ -498,15 +532,14 @@
         intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
         mContext.sendStickyBroadcast(intent);
     }
-    
+
     private boolean checkPhoneStatePermission(String method) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
                 == PackageManager.PERMISSION_GRANTED) {
             return true;
         }
         String msg = "Modify Phone State Permission Denial: " + method + " from pid="
-                + Binder.getCallingPid()
-                + ", uid=" + Binder.getCallingUid();
+                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
         Log.w(TAG, msg);
         return false;
     }
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 0387be5..a695eba 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -25,6 +25,7 @@
 import android.os.Parcel;
 import android.os.Process;
 import android.os.ServiceManager;
+import android.telephony.SignalStrength;
 import android.util.Log;
 
 import java.io.FileDescriptor;
@@ -177,10 +178,10 @@
         }
     }
     
-    public void notePhoneSignalStrength(int asu) {
+    public void notePhoneSignalStrength(SignalStrength signalStrength) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.notePhoneSignalStrengthLocked(asu);
+            mStats.notePhoneSignalStrengthLocked(signalStrength);
         }
     }
     
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 0b161d6..af94100 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -41,6 +41,7 @@
 import android.provider.Settings;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.text.format.DateFormat;
 import android.util.Log;
@@ -57,6 +58,7 @@
 import com.android.internal.location.GpsLocationProvider;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.cdma.EriInfo;
 import com.android.internal.telephony.cdma.TtyIntent;
 import com.android.server.am.BatteryStatsService;
 
@@ -111,45 +113,140 @@
     // phone
     private TelephonyManager mPhone;
     private IBinder mPhoneIcon;
+    private IBinder mPhoneEvdoIcon;
 
     //***** Signal strength icons
     private IconData mPhoneData;
+    private IconData mPhoneEvdoData;
     //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,
-            com.android.internal.R.drawable.stat_sys_signal_2,
-            com.android.internal.R.drawable.stat_sys_signal_3,
-            com.android.internal.R.drawable.stat_sys_signal_4
-        };
+        com.android.internal.R.drawable.stat_sys_signal_0,
+        com.android.internal.R.drawable.stat_sys_signal_1,
+        com.android.internal.R.drawable.stat_sys_signal_2,
+        com.android.internal.R.drawable.stat_sys_signal_3,
+        com.android.internal.R.drawable.stat_sys_signal_4
+    };
     private static final int[] sSignalImages_r = new int[] {
-            com.android.internal.R.drawable.stat_sys_r_signal_0,
-            com.android.internal.R.drawable.stat_sys_r_signal_1,
-            com.android.internal.R.drawable.stat_sys_r_signal_2,
-            com.android.internal.R.drawable.stat_sys_r_signal_3,
-            com.android.internal.R.drawable.stat_sys_r_signal_4
-        };
+        com.android.internal.R.drawable.stat_sys_r_signal_0,
+        com.android.internal.R.drawable.stat_sys_r_signal_1,
+        com.android.internal.R.drawable.stat_sys_r_signal_2,
+        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
+        com.android.internal.R.drawable.stat_sys_signal_cdma_0,
+        com.android.internal.R.drawable.stat_sys_signal_cdma_1,
+        com.android.internal.R.drawable.stat_sys_signal_cdma_2,
+        com.android.internal.R.drawable.stat_sys_signal_cdma_3,
+        com.android.internal.R.drawable.stat_sys_signal_cdma_4
     };
-    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[] sRoamingIndicatorImages_cdma = new int[] {
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
+        // 1 is Standard Roaming Indicator OFF
+        // TODO T: image never used, remove and put 0 instead?
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+        // 2 is Standard Roaming Indicator FLASHING
+        // TODO T: image never used, remove and put 0 instead?
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+        // 3-12 Standard ERI
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //3
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+        // 13-63 Reserved for Standard ERI
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //13
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+
+        // 64-127 Reserved for Non Standard (Operator Specific) ERI
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0, //64
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0,
+        com.android.internal.R.drawable.stat_sys_roaming_cdma_0 //83
+
+        // 128-255 Reserved
     };
-    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
+    // EVDO
+    private static final int[] sSignalImages_evdo = new int[] {
+        com.android.internal.R.drawable.stat_sys_signal_evdo_0,
+        com.android.internal.R.drawable.stat_sys_signal_evdo_1,
+        com.android.internal.R.drawable.stat_sys_signal_evdo_2,
+        com.android.internal.R.drawable.stat_sys_signal_evdo_3,
+        com.android.internal.R.drawable.stat_sys_signal_evdo_4
     };
 
     //***** Data connection icons
@@ -179,12 +276,14 @@
         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,
+        com.android.internal.R.drawable.stat_sys_data_dormant_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,
+        com.android.internal.R.drawable.stat_sys_data_dormant_1xrtt,
     };
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
@@ -194,7 +293,7 @@
     int mDataState = TelephonyManager.DATA_DISCONNECTED;
     int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
     ServiceState mServiceState;
-    int mSignalAsu = -1;
+    SignalStrength mSignalStrength;
 
     // data connection
     private IBinder mDataIcon;
@@ -249,6 +348,10 @@
     private IBinder mTTYModeIcon;
     private IconData mTTYModeEnableIconData;
 
+    // Cdma Roaming Indicator, ERI
+    private IBinder mCdmaRoamingIndicatorIcon;
+    private IconData mCdmaRoamingIndicatorIconData;
+
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -306,6 +409,7 @@
     private StatusBarPolicy(Context context, StatusBarService service) {
         mContext = context;
         mService = service;
+        mSignalStrength = new SignalStrength();
         mBatteryStats = BatteryStatsService.getService();
 
         // clock
@@ -321,14 +425,21 @@
 
         // phone_signal
         mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
-        mPhoneData = IconData.makeIcon("phone_signal", 
+        mPhoneData = IconData.makeIcon("phone_signal",
                 null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
         mPhoneIcon = service.addIcon(mPhoneData, null);
+
+        // phone_evdo_signal
+        mPhoneEvdoData = IconData.makeIcon("phone_evdo_signal",
+                null, com.android.internal.R.drawable.stat_sys_signal_evdo_0, 0, 0);
+        mPhoneEvdoIcon = service.addIcon(mPhoneEvdoData, null);
+        service.setIconVisibility(mPhoneEvdoIcon, false);
+
         // register for phone state notifications.
         ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
                 .listen(mPhoneStateListener,
                           PhoneStateListener.LISTEN_SERVICE_STATE
-                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTH
+                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
                         | PhoneStateListener.LISTEN_CALL_STATE
                         | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                         | PhoneStateListener.LISTEN_DATA_ACTIVITY);
@@ -351,6 +462,12 @@
         mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
         service.setIconVisibility(mTTYModeIcon, false);
 
+        // Cdma Roaming Indicator, ERI
+        mCdmaRoamingIndicatorIconData = IconData.makeIcon("cdma_eri",
+                null, com.android.internal.R.drawable.stat_sys_roaming_cdma_0, 0, 0);
+        mCdmaRoamingIndicatorIcon = service.addIcon(mCdmaRoamingIndicatorIconData, null);
+        service.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+
         // bluetooth status
         mBluetoothData = IconData.makeIcon("bluetooth",
                 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
@@ -666,8 +783,8 @@
 
     private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
         @Override
-        public void onSignalStrengthChanged(int asu) {
-            mSignalAsu = asu;
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            mSignalStrength = signalStrength;
             updateSignalStrength();
         }
 
@@ -675,6 +792,7 @@
         public void onServiceStateChanged(ServiceState state) {
             mServiceState = state;
             updateSignalStrength();
+            updateCdmaRoamingIcon();
             updateDataIcon();
         }
 
@@ -696,7 +814,6 @@
             updateDataIcon();
         }
     };
-    
 
     private final void updateSimState(Intent intent) {
         String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
@@ -723,25 +840,51 @@
         updateDataIcon();
     }
 
-    private final void updateSignalStrength() {
-        int asu = mSignalAsu;
-        ServiceState ss = mServiceState;
+    // TODO(Teleca): I've add isCdma() to reduce some code duplication and simplify.
+    //               Please validate the correctness of these changes
+    private boolean isCdma() {
+        // Is this equivalent, if so it seems simpler?
+//        return ((mPhone != null) && (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA));
 
-        boolean hasService = true;
-        
-        if (ss != null) {
-            int state = ss.getState();
-            switch (state) {
-                case ServiceState.STATE_OUT_OF_SERVICE:
-                case ServiceState.STATE_POWER_OFF:
-                    hasService = false;
-                    break;
+        if (mServiceState != null) {
+            switch(mServiceState.getRadioTechnology()) {
+                case ServiceState.RADIO_TECHNOLOGY_1xRTT:
+                case ServiceState.RADIO_TECHNOLOGY_EVDO_0:
+                case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
+                case ServiceState.RADIO_TECHNOLOGY_IS95A:
+                case ServiceState.RADIO_TECHNOLOGY_IS95B:
+                  return true;
+                default:
+                  return false;
             }
         } else {
-            hasService = false;
+            return false;
         }
+    }
 
-        if (!hasService) {
+    // TODO(Teleca): I've add hasService() to reduce some code duplication and simplify.
+    //               Please validate the correctness of these changes.
+    private boolean hasService() {
+        if (mServiceState != null) {
+            switch (mServiceState.getState()) {
+                case ServiceState.STATE_OUT_OF_SERVICE:
+                case ServiceState.STATE_POWER_OFF:
+                    return false;
+                default:
+                    return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    private final void updateSignalStrength() {
+        int iconLevel = -1;
+        int evdoIconLevel = -1;
+        int[] iconList;
+        int[] evdoIconList;
+
+        if (!hasService()) {
             //Log.d(TAG, "updateSignalStrength: no service");
             if (Settings.System.getInt(mContext.getContentResolver(),
                     Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
@@ -750,48 +893,92 @@
                 mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
             }
             mService.updateIcon(mPhoneIcon, mPhoneData, null);
+            mService.setIconVisibility(mPhoneEvdoIcon,false);
             return;
         }
 
-        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
-        // asu = 0 (-113dB or less) is very weak
-        // signal, its better to show 0 bars to the user in such cases.
-        // asu = 99 is a special case, where the signal strength is unknown.
-        if (asu <= 0 || asu == 99) asu = 0;
-        else if (asu >= 16) asu = 4;
-        else if (asu >= 8)  asu = 3;
-        else if (asu >= 4)  asu = 2;
-        else asu = 1;
+        if (!isCdma()) {
+            int asu = mSignalStrength.getGsmSignalStrength();
 
-        int[] iconList;
-        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;
+            // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+            // asu = 0 (-113dB or less) is very weak
+            // signal, its better to show 0 bars to the user in such cases.
+            // asu = 99 is a special case, where the signal strength is unknown.
+            if (asu <= 0 || asu == 99) iconLevel = 0;
+            else if (asu >= 16) iconLevel = 4;
+            else if (asu >= 8)  iconLevel = 3;
+            else if (asu >= 4)  iconLevel = 2;
+            else iconLevel = 1;
+
+            if (mPhone.isNetworkRoaming()) {
+                iconList = sSignalImages_r;
+            } else {
+                iconList = sSignalImages;
             }
-        } else if (mPhone.isNetworkRoaming()) {
-            iconList = sSignalImages_r;
         } else {
-            iconList = sSignalImages;
+            iconList = this.sSignalImages_cdma;
+
+            int cdmaDbm = mSignalStrength.getCdmaDbm();
+            int cdmaEcio = mSignalStrength.getCdmaEcio();
+            int levelDbm = 0;
+            int levelEcio = 0;
+
+            if (cdmaDbm >= -75) levelDbm = 4;
+            else if (cdmaDbm >= -85) levelDbm = 3;
+            else if (cdmaDbm >= -95) levelDbm = 2;
+            else if (cdmaDbm >= -100) levelDbm = 1;
+            else levelDbm = 0;
+
+            // Ec/Io are in dB*10
+            if (cdmaEcio >= -90) levelEcio = 4;
+            else if (cdmaEcio >= -110) levelEcio = 3;
+            else if (cdmaEcio >= -130) levelEcio = 2;
+            else if (cdmaEcio >= -150) levelEcio = 1;
+            else levelEcio = 0;
+
+            iconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio;
         }
 
-        mPhoneData.iconId = iconList[asu];
+        if ((mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
+                  || (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
+            // Use Evdo icon
+            evdoIconList = this.sSignalImages_evdo;
+
+            int evdoEcio = mSignalStrength.getEvdoEcio();
+            int evdoSnr = mSignalStrength.getEvdoSnr();
+            int levelEvdoEcio = 0;
+            int levelEvdoSnr = 0;
+
+            // Ec/Io are in dB*10
+            if (evdoEcio >= -650) levelEvdoEcio = 4;
+            else if (evdoEcio >= -750) levelEvdoEcio = 3;
+            else if (evdoEcio >= -900) levelEvdoEcio = 2;
+            else if (evdoEcio >= -1050) levelEvdoEcio = 1;
+            else levelEvdoEcio = 0;
+
+            if (evdoSnr > 7) levelEvdoSnr = 4;
+            else if (evdoSnr > 5) levelEvdoSnr = 3;
+            else if (evdoSnr > 3) levelEvdoSnr = 2;
+            else if (evdoSnr > 1) levelEvdoSnr = 1;
+            else levelEvdoSnr = 0;
+
+            evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr;
+
+            mPhoneEvdoData.iconId = evdoIconList[evdoIconLevel];
+            mService.updateIcon(mPhoneEvdoIcon, mPhoneEvdoData, null);
+            mService.setIconVisibility(mPhoneEvdoIcon,true);
+        } else {
+            mService.setIconVisibility(mPhoneEvdoIcon,false);
+        }
+
+        mPhoneData.iconId = iconList[iconLevel];
         mService.updateIcon(mPhoneIcon, mPhoneData, null);
     }
 
     private final void updateDataNetType() {
         int net = mPhone.getNetworkType();
-        ServiceState ss = this.mServiceState;
 
         switch (net) {
-
         case TelephonyManager.NETWORK_TYPE_EDGE:
             mDataIconList = sDataNetType_e;
             break;
@@ -819,32 +1006,51 @@
         int iconId;
         boolean visible = true;
 
-        if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
-            int data = mDataState;
-
-            int[] list = mDataIconList;
-
-            ServiceState ss = mServiceState;
-
-            boolean hasService = false;
-
-            if (ss != null) {
-                hasService = (ss.getState() == ServiceState.STATE_IN_SERVICE);
+        if (!isCdma()) {
+            // GSM case, we have to check also the sim state
+            if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
+                if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
+                    switch (mDataActivity) {
+                        case TelephonyManager.DATA_ACTIVITY_IN:
+                            iconId = mDataIconList[1];
+                            break;
+                        case TelephonyManager.DATA_ACTIVITY_OUT:
+                            iconId = mDataIconList[2];
+                            break;
+                        case TelephonyManager.DATA_ACTIVITY_INOUT:
+                            iconId = mDataIconList[3];
+                            break;
+                        default:
+                            iconId = mDataIconList[0];
+                            break;
+                    }
+                    mDataData.iconId = iconId;
+                    mService.updateIcon(mDataIcon, mDataData, null);
+                } else {
+                    visible = false;
+                }
+            } else {
+                mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
+                mService.updateIcon(mDataIcon, mDataData, null);
             }
-
-            if (hasService && data == TelephonyManager.DATA_CONNECTED) {
+        } else {
+            // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
+            if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
                 switch (mDataActivity) {
                     case TelephonyManager.DATA_ACTIVITY_IN:
-                        iconId = list[1];
+                        iconId = mDataIconList[1];
                         break;
                     case TelephonyManager.DATA_ACTIVITY_OUT:
-                        iconId = list[2];
+                        iconId = mDataIconList[2];
                         break;
                     case TelephonyManager.DATA_ACTIVITY_INOUT:
-                        iconId = list[3];
+                        iconId = mDataIconList[3];
+                        break;
+                    case TelephonyManager.DATA_ACTIVITY_DORMANT:
+                        iconId = mDataIconList[4];
                         break;
                     default:
-                        iconId = list[0];
+                        iconId = mDataIconList[0];
                         break;
                 }
                 mDataData.iconId = iconId;
@@ -852,10 +1058,8 @@
             } else {
                 visible = false;
             }
-        } else {
-            mDataData.iconId = com.android.internal.R.drawable.stat_sys_no_sim;
-            mService.updateIcon(mDataIcon, mDataData, null);
         }
+
         long ident = Binder.clearCallingIdentity();
         try {
             mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
@@ -863,6 +1067,7 @@
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
+
         if (mDataIconVisible != visible) {
             mService.setIconVisibility(mDataIcon, visible);
             mDataIconVisible = visible;
@@ -873,7 +1078,7 @@
         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         final int ringerMode = audioManager.getRingerMode();
         final boolean visible = ringerMode == AudioManager.RINGER_MODE_SILENT ||
-                ringerMode == AudioManager.RINGER_MODE_VIBRATE; 
+                ringerMode == AudioManager.RINGER_MODE_VIBRATE;
         final int iconId = audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)
                 ? com.android.internal.R.drawable.stat_sys_ringer_vibrate
                 : com.android.internal.R.drawable.stat_sys_ringer_silent;
@@ -905,7 +1110,7 @@
         } else {
             return;
         }
-        
+
         if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED ||
                 mBluetoothA2dpState == BluetoothA2dp.STATE_CONNECTED ||
                 mBluetoothA2dpState == BluetoothA2dp.STATE_PLAYING) {
@@ -920,15 +1125,15 @@
     private final void updateWifi(Intent intent) {
         final String action = intent.getAction();
         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) {
                 // If disabled, hide the icon. (We show icon when connected.)
                 mService.setIconVisibility(mWifiIcon, false);
             }
-            
+
         } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
             final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
                                                            false);
@@ -937,9 +1142,9 @@
             }
         } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
 
-            final NetworkInfo networkInfo = (NetworkInfo) 
+            final NetworkInfo networkInfo = (NetworkInfo)
                     intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-            
+
             int iconId;
             if (networkInfo != null && networkInfo.isConnected()) {
                 mIsWifiConnected = true;
@@ -986,18 +1191,18 @@
         if (action.equals(GpsLocationProvider.GPS_FIX_CHANGE_ACTION) && enabled) {
             // GPS is getting fixes
             mService.updateIcon(mGpsIcon, mGpsFixIconData, null);
-            mService.setIconVisibility(mGpsIcon, true);           
+            mService.setIconVisibility(mGpsIcon, true);
         } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
             // GPS is off
-            mService.setIconVisibility(mGpsIcon, false);           
+            mService.setIconVisibility(mGpsIcon, false);
         } else {
             // GPS is on, but not receiving fixes
             mService.updateIcon(mGpsIcon, mGpsEnabledIconData, null);
-            mService.setIconVisibility(mGpsIcon, true);           
+            mService.setIconVisibility(mGpsIcon, true);
         }
     }
 
-    private final void updateTTY(Intent intent) {       
+    private final void updateTTY(Intent intent) {
         final String action = intent.getAction();
         final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
 
@@ -1007,14 +1212,59 @@
             // TTY is on
             Log.i(TAG, "updateTTY: set TTY on");
             mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
-            mService.setIconVisibility(mTTYModeIcon, true);          
+            mService.setIconVisibility(mTTYModeIcon, true);
         } else {
             // TTY is off
             Log.i(TAG, "updateTTY: set TTY off");
-            mService.setIconVisibility(mTTYModeIcon, false);           
+            mService.setIconVisibility(mTTYModeIcon, false);
         }
     }
 
+    private final void updateCdmaRoamingIcon() {
+        if (!hasService()) {
+            mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+        }
+
+        if (!isCdma()) {
+            mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+        }
+
+        int[] iconList = sRoamingIndicatorImages_cdma;
+        int iconIndex = mPhone.getCdmaEriIconIndex();
+        int iconMode = mPhone.getCdmaEriIconMode();
+
+        if (iconIndex == -1) {
+            Log.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
+            return;
+        }
+
+        if (iconMode == -1) {
+            Log.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
+            return;
+        }
+
+        if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
+            Log.d(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
+            mService.setIconVisibility(mCdmaRoamingIndicatorIcon, false);
+            return;
+        }
+
+        switch (iconMode) {
+            case EriInfo.ROAMING_ICON_MODE_NORMAL:
+                mCdmaRoamingIndicatorIconData.iconId = iconList[iconIndex];
+                mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
+                mService.setIconVisibility(mCdmaRoamingIndicatorIcon, true);
+                break;
+            case EriInfo.ROAMING_ICON_MODE_FLASH:
+                mCdmaRoamingIndicatorIconData.iconId = com.android.internal.R.drawable.stat_sys_roaming_cdma_flash;
+                mService.updateIcon(mCdmaRoamingIndicatorIcon, mCdmaRoamingIndicatorIconData, null);
+                break;
+
+        }
+        mService.updateIcon(mPhoneIcon, mPhoneData, null);
+    }
+
+
     private class StatusBarHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
@@ -1028,6 +1278,3 @@
         }
     }
 }
-
-
-
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index bb5f126..1483522 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -67,8 +67,8 @@
 
         // 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)) {
+        if (RILConstants.CDMA_PHONE == SystemProperties.getInt(
+                Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.CDMA_PHONE)) {
             return new CdmaCellLocation(bundle);
         } else {
             return new GsmCellLocation(bundle);
@@ -90,12 +90,11 @@
 
         // 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)) {
+        if (RILConstants.CDMA_PHONE == SystemProperties.getInt(
+                Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.CDMA_PHONE)) {
             return new CdmaCellLocation();
         } else {
             return new GsmCellLocation();
         }
     }
-
 }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index df6860b..8abafae 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -4,6 +4,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.CellLocation;
 import android.util.Log;
 
@@ -42,10 +43,10 @@
     /**
      * Listen for changes to the network signal strength (cellular).
      * <p>
-     * Example: The status bar uses this to control the signal-strength
-     * icon.
      *
      * @see #onSignalStrengthChanged
+     *
+     * TODO: @deprecated to be deprecated by LISTEN_SIGNAL_STRENGTHS, @see #onSignalStrengthsChanged
      */
     public static final int LISTEN_SIGNAL_STRENGTH                          = 0x00000002;
 
@@ -107,6 +108,18 @@
      */
     public static final int LISTEN_DATA_ACTIVITY                            = 0x00000080;
 
+    /**
+     * Listen for changes to the network signal strengths (cellular).
+     * <p>
+     * Example: The status bar uses this to control the signal-strength
+     * icon.
+     *
+     * @see #onSignalStrengthsChanged
+     *
+     * @hide
+     */
+    public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100;
+
     public PhoneStateListener() {
     }
 
@@ -129,6 +142,7 @@
      * @see ServiceState#STATE_IN_SERVICE
      * @see ServiceState#STATE_OUT_OF_SERVICE
      * @see ServiceState#STATE_POWER_OFF
+     * @deprecated, @see #onSignalStrengthsChanged
      */
     public void onSignalStrengthChanged(int asu) {
         // default implementation empty
@@ -185,12 +199,27 @@
      * @see TelephonyManager#DATA_ACTIVITY_IN
      * @see TelephonyManager#DATA_ACTIVITY_OUT
      * @see TelephonyManager#DATA_ACTIVITY_INOUT
+     * @see TelephonyManager#DATA_ACTIVITY_DORMANT
      */
     public void onDataActivity(int direction) {
         // default implementation empty
     }
 
     /**
+     * Callback invoked when network signal strengths changes.
+     *
+     * @see ServiceState#STATE_EMERGENCY_ONLY
+     * @see ServiceState#STATE_IN_SERVICE
+     * @see ServiceState#STATE_OUT_OF_SERVICE
+     * @see ServiceState#STATE_POWER_OFF
+     *
+     * @hide
+     */
+    public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+        // default implementation empty
+    }
+
+    /**
      * The callback methods need to be called on the handler thread where
      * this object was created.  If the binder did that for us it'd be nice.
      */
@@ -229,6 +258,9 @@
         public void onDataActivity(int direction) {
             Message.obtain(mHandler, LISTEN_DATA_ACTIVITY, direction, 0, null).sendToTarget();
         }
+        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+            Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength).sendToTarget();
+        }
     };
 
     Handler mHandler = new Handler() {
@@ -259,6 +291,9 @@
                 case LISTEN_DATA_ACTIVITY:
                     PhoneStateListener.this.onDataActivity(msg.arg1);
                     break;
+                case LISTEN_SIGNAL_STRENGTHS:
+                    PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
+                    break;
             }
         }
     };
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 4de0954..50c4d41 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -99,12 +99,9 @@
     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;
@@ -115,6 +112,8 @@
     private boolean mCssIndicator;
     private int mNetworkId;
     private int mSystemId;
+    private int mCdmaRoamingIndicator;
+    private int mCdmaDefaultRoamingIndicator;
 
     /**
      * Create a new ServiceState from a intent notifier Bundle
@@ -159,7 +158,8 @@
         mCssIndicator = s.mCssIndicator;
         mNetworkId = s.mNetworkId;
         mSystemId = s.mSystemId;
-        mExtendedCdmaRoaming = s.mExtendedCdmaRoaming;
+        mCdmaRoamingIndicator = s.mCdmaRoamingIndicator;
+        mCdmaDefaultRoamingIndicator = s.mCdmaDefaultRoamingIndicator;
     }
 
     /**
@@ -176,7 +176,8 @@
         mCssIndicator = (in.readInt() != 0);
         mNetworkId = in.readInt();
         mSystemId = in.readInt();
-        mExtendedCdmaRoaming = in.readInt();
+        mCdmaRoamingIndicator = in.readInt();
+        mCdmaDefaultRoamingIndicator = in.readInt();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -190,7 +191,8 @@
         out.writeInt(mCssIndicator ? 1 : 0);
         out.writeInt(mNetworkId);
         out.writeInt(mSystemId);
-        out.writeInt(mExtendedCdmaRoaming);
+        out.writeInt(mCdmaRoamingIndicator);
+        out.writeInt(mCdmaDefaultRoamingIndicator);
     }
 
     public int describeContents() {
@@ -231,15 +233,25 @@
         return mRoaming;
     }
 
-    /** @hide */
-    public int getExtendedCdmaRoaming(){
-        return this.mExtendedCdmaRoaming;
+    /**
+     * @hide
+     */
+    public int getCdmaRoamingIndicator(){
+        return this.mCdmaRoamingIndicator;
+    }
+
+    /**
+     * @hide
+     */
+    public int getCdmaDefaultRoamingIndicator(){
+        return this.mCdmaDefaultRoamingIndicator;
     }
 
     /**
      * Get current registered operator name in long alphanumeric format
      *
      * In GSM/UMTS, long format can be upto 16 characters long
+     * In CDMA, returns the ERI text, if set, otherwise the ONS
      *
      * @return long name of operator, null if unregistered or unknown
      */
@@ -289,7 +301,8 @@
                 + ((null == mOperatorAlphaLong) ? 0 : mOperatorAlphaLong.hashCode())
                 + ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
                 + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
-                + (mExtendedCdmaRoaming));
+                + mCdmaRoamingIndicator
+                + mCdmaDefaultRoamingIndicator);
     }
 
     @Override
@@ -316,7 +329,9 @@
                 && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
                 && equalsHandlesNulls(mNetworkId, s.mNetworkId)
                 && equalsHandlesNulls(mSystemId, s.mSystemId)
-                && equalsHandlesNulls(mExtendedCdmaRoaming, s.mExtendedCdmaRoaming));
+                && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
+                && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
+                        s.mCdmaDefaultRoamingIndicator));
     }
 
     @Override
@@ -363,9 +378,10 @@
                 + " " + (mIsManualNetworkSelection ? "(manual)" : "")
                 + " " + radioTechnology
                 + " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
-                + "NetworkId: " + mNetworkId
-                + "SystemId: " + mSystemId
-                + "ExtendedCdmaRoaming: " + mExtendedCdmaRoaming);
+                + " " + mNetworkId
+                + " " + mSystemId
+                + "RoamInd: " + mCdmaRoamingIndicator
+                + "DefRoamInd: " + mCdmaDefaultRoamingIndicator);
     }
 
     public void setStateOutOfService() {
@@ -379,7 +395,8 @@
         mCssIndicator = false;
         mNetworkId = -1;
         mSystemId = -1;
-        mExtendedCdmaRoaming = -1;
+        mCdmaRoamingIndicator = -1;
+        mCdmaDefaultRoamingIndicator = -1;
     }
 
     public void setStateOff() {
@@ -393,7 +410,8 @@
         mCssIndicator = false;
         mNetworkId = -1;
         mSystemId = -1;
-        mExtendedCdmaRoaming = -1;
+        mCdmaRoamingIndicator = -1;
+        mCdmaDefaultRoamingIndicator = -1;
     }
 
     public void setState(int state) {
@@ -404,9 +422,18 @@
         mRoaming = roaming;
     }
 
-    /** @hide */
-    public void setExtendedCdmaRoaming (int roaming) {
-        this.mExtendedCdmaRoaming = roaming;
+    /**
+     * @hide
+     */
+    public void setCdmaRoamingIndicator(int roaming) {
+        this.mCdmaRoamingIndicator = roaming;
+    }
+
+    /**
+     * @hide
+     */
+    public void setCdmaDefaultRoamingIndicator (int roaming) {
+        this.mCdmaDefaultRoamingIndicator = roaming;
     }
 
     public void setOperatorName(String longName, String shortName, String numeric) {
@@ -415,6 +442,16 @@
         mOperatorNumeric = numeric;
     }
 
+    /**
+     * In CDMA mOperatorAlphaLong can be set from the ERI
+     * text, this is done from the CDMAPhone and not from the CdmaServiceStateTracker
+     *
+     * @hide
+     */
+    public void setCdmaEriText(String longName) {
+        mOperatorAlphaLong = longName;
+    }
+
     public void setIsManualSelection(boolean isManual) {
         mIsManualNetworkSelection = isManual;
     }
@@ -447,7 +484,8 @@
         mCssIndicator = m.getBoolean("cssIndicator");
         mNetworkId = m.getInt("networkId");
         mSystemId = m.getInt("systemId");
-        mExtendedCdmaRoaming = m.getInt("extendedCdmaRoaming");
+        mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
+        mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
     }
 
     /**
@@ -467,7 +505,8 @@
         m.putBoolean("cssIndicator", mCssIndicator);
         m.putInt("networkId", mNetworkId);
         m.putInt("systemId", mSystemId);
-        m.putInt("extendedCdmaRoaming", mExtendedCdmaRoaming);
+        m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
+        m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
     }
 
     //***** CDMA
diff --git a/telephony/java/android/telephony/SignalStrength.aidl b/telephony/java/android/telephony/SignalStrength.aidl
new file mode 100644
index 0000000..c25411e
--- /dev/null
+++ b/telephony/java/android/telephony/SignalStrength.aidl
@@ -0,0 +1,22 @@
+/* //device/java/android/android/content/Intent.aidl
+**
+** Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
+** 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.telephony;
+
+parcelable SignalStrength;
+
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
new file mode 100644
index 0000000..8ed0065
--- /dev/null
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
+ * 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.telephony;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Contains phone signal strength related information.
+ *
+ * @hide
+ */
+public class SignalStrength implements Parcelable {
+
+    static final String LOG_TAG = "PHONE";
+
+    private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
+    private int mGsmBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+    private int mCdmaDbm;   // This value is the RSSI value
+    private int mCdmaEcio;  // This value is the Ec/Io
+    private int mEvdoDbm;   // This value is the EVDO RSSI value
+    private int mEvdoEcio;  // This value is the EVDO Ec/Io
+    private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
+
+    private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
+
+    /**
+     * Create a new SignalStrength from a intent notifier Bundle
+     *
+     * This method is used by PhoneStateIntentReceiver and maybe by
+     * external applications.
+     *
+     * @param m Bundle from intent notifier
+     * @return newly created SignalStrength
+     *
+     */
+    public static SignalStrength newFromBundle(Bundle m) {
+        SignalStrength ret;
+        ret = new SignalStrength();
+        ret.setFromNotifierBundle(m);
+        return ret;
+    }
+
+    /**
+     * Empty constructor
+     *
+     */
+    public SignalStrength() {
+        mGsmSignalStrength = 99;
+        mGsmBitErrorRate = -1;
+        mCdmaDbm = -1;
+        mCdmaEcio = -1;
+        mEvdoDbm = -1;
+        mEvdoEcio = -1;
+        mEvdoSnr = -1;
+        isGsm = true;
+    }
+
+    /**
+     * Constructor
+     *
+     */
+    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr, boolean gsm) {
+        mGsmSignalStrength = gsmSignalStrength;
+        mGsmBitErrorRate = gsmBitErrorRate;
+        mCdmaDbm = cdmaDbm;
+        mCdmaEcio = cdmaEcio;
+        mEvdoDbm = evdoDbm;
+        mEvdoEcio = evdoEcio;
+        mEvdoSnr = evdoSnr;
+        isGsm = gsm;
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     */
+    public SignalStrength(SignalStrength s) {
+        copyFrom(s);
+    }
+
+    /**
+     * @hide
+     */
+    protected void copyFrom(SignalStrength s) {
+        mGsmSignalStrength = s.mGsmSignalStrength;
+        mGsmBitErrorRate = s.mGsmBitErrorRate;
+        mCdmaDbm = s.mCdmaDbm;
+        mCdmaEcio = s.mCdmaEcio;
+        mEvdoDbm = s.mEvdoDbm;
+        mEvdoEcio = s.mEvdoEcio;
+        mEvdoSnr = s.mEvdoSnr;
+        isGsm = s.isGsm;
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel.
+     */
+    public SignalStrength(Parcel in) {
+        mGsmSignalStrength = in.readInt();
+        mGsmBitErrorRate = in.readInt();
+        mCdmaDbm = in.readInt();
+        mCdmaEcio = in.readInt();
+        mEvdoDbm = in.readInt();
+        mEvdoEcio = in.readInt();
+        mEvdoSnr = in.readInt();
+        isGsm = (in.readInt() != 0);
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mGsmSignalStrength);
+        out.writeInt(mGsmBitErrorRate);
+        out.writeInt(mCdmaDbm);
+        out.writeInt(mCdmaEcio);
+        out.writeInt(mEvdoDbm);
+        out.writeInt(mEvdoEcio);
+        out.writeInt(mEvdoSnr);
+        out.writeInt(isGsm ? 1 : 0);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
+        public SignalStrength createFromParcel(Parcel in) {
+            return new SignalStrength(in);
+        }
+
+        public SignalStrength[] newArray(int size) {
+            return new SignalStrength[size];
+        }
+    };
+
+    /**
+     * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS 27.007 8.5
+     */
+    public int getGsmSignalStrength() {
+        return this.mGsmSignalStrength;
+    }
+
+    /**
+     * Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5
+     */
+    public int getGsmBitErrorRate() {
+        return this.mGsmBitErrorRate;
+    }
+
+    /**
+     * Get the CDMA RSSI value in dBm
+     */
+    public int getCdmaDbm() {
+        return this.mCdmaDbm;
+    }
+
+    /**
+     * Get the CDMA Ec/Io value in dB*10
+     */
+    public int getCdmaEcio() {
+        return this.mCdmaEcio;
+    }
+
+    /**
+     * Get the EVDO RSSI value in dBm
+     */
+    public int getEvdoDbm() {
+        return this.mEvdoDbm;
+    }
+
+    /**
+     * Get the EVDO Ec/Io value in dB*10
+     */
+    public int getEvdoEcio() {
+        return this.mEvdoEcio;
+    }
+
+    /**
+     * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
+     */
+    public int getEvdoSnr() {
+        return this.mEvdoSnr;
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isGsm() {
+        return this.isGsm;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public int hashCode() {
+        return ((mGsmSignalStrength * 0x1234)
+                + mGsmBitErrorRate
+                + mCdmaDbm + mCdmaEcio
+                + mEvdoDbm + mEvdoEcio + mEvdoSnr
+                + (isGsm ? 1 : 0));
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean equals (Object o) {
+        SignalStrength s;
+
+        try {
+            s = (SignalStrength) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return (mGsmSignalStrength == s.mGsmSignalStrength
+                && mGsmBitErrorRate == s.mGsmBitErrorRate
+                && mCdmaDbm == s.mCdmaDbm
+                && mCdmaEcio == s.mCdmaEcio
+                && mEvdoDbm == s.mEvdoDbm
+                && mEvdoEcio == s.mEvdoEcio
+                && mEvdoSnr == s.mEvdoSnr
+                && isGsm == s.isGsm);
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public String toString() {
+        return ("SignalStrength:"
+                + " " + mGsmSignalStrength
+                + " " + mGsmBitErrorRate
+                + " " + mCdmaDbm
+                + " " + mCdmaEcio
+                + " " + mEvdoDbm
+                + " " + mEvdoEcio
+                + " " + mEvdoSnr
+                + " " + (isGsm ? "gsm" : "cdma"));
+    }
+
+    /**
+     * 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
+     * @hide
+     */
+    private static boolean equalsHandlesNulls (Object a, Object b) {
+        return (a == null) ? (b == null) : a.equals (b);
+    }
+
+    /**
+     * Set SignalStrength based on intent notifier map
+     *
+     * @param m intent notifier map
+     * @hide
+     */
+    private void setFromNotifierBundle(Bundle m) {
+        mGsmSignalStrength = m.getInt("GsmSignalStrength");
+        mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
+        mCdmaDbm = m.getInt("CdmaDbm");
+        mCdmaEcio = m.getInt("CdmaEcio");
+        mEvdoDbm = m.getInt("EvdoDbm");
+        mEvdoEcio = m.getInt("EvdoEcio");
+        mEvdoSnr = m.getInt("EvdoSnr");
+        isGsm = m.getBoolean("isGsm");
+    }
+
+    /**
+     * Set intent notifier Bundle based on SignalStrength
+     *
+     * @param m intent notifier Bundle
+     * @hide
+     */
+    public void fillInNotifierBundle(Bundle m) {
+        m.putInt("GsmSignalStrength", mGsmSignalStrength);
+        m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
+        m.putInt("CdmaDbm", mCdmaDbm);
+        m.putInt("CdmaEcio", mCdmaEcio);
+        m.putInt("EvdoDbm", mEvdoDbm);
+        m.putInt("EvdoEcio", mEvdoEcio);
+        m.putInt("EvdoSnr", mEvdoSnr);
+        m.putBoolean("isGsm", Boolean.valueOf(isGsm));
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 559542a..49a7750 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -192,8 +192,9 @@
     /**
      * Returns the current location of the device.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION
-     * ACCESS_COARSE_LOCATION}.
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.
      */
     public CellLocation getCellLocation() {
         try {
@@ -639,6 +640,9 @@
     /** Data connection activity: Currently both sending and receiving
      *  IP PPP traffic. */
     public static final int DATA_ACTIVITY_INOUT = DATA_ACTIVITY_IN | DATA_ACTIVITY_OUT;
+    /** Data connection is active, but physical link is down */
+    /** @hide */
+    public static final int DATA_ACTIVITY_DORMANT = 0x00000004;
 
     /**
      * Returns a constant indicating the type of activity on a data connection
@@ -648,6 +652,7 @@
      * @see #DATA_ACTIVITY_IN
      * @see #DATA_ACTIVITY_OUT
      * @see #DATA_ACTIVITY_INOUT
+     * @see #DATA_ACTIVITY_DORMANT
      */
     public int getDataActivity() {
         try {
@@ -729,4 +734,48 @@
             // system process dead
         }
     }
+
+    /**
+     * Returns the CDMA ERI icon index to display
+     *
+     * @hide
+     */
+    public int getCdmaEriIconIndex() {
+        try {
+            return getITelephony().getCdmaEriIconIndex();
+        } catch (RemoteException ex) {
+            // the phone process is restarting.
+            return -1;
+        }
+    }
+
+    /**
+     * Returns the CDMA ERI icon mode,
+     * 0 - ON
+     * 1 - FLASHING
+     *
+     * @hide
+     */
+    public int getCdmaEriIconMode() {
+        try {
+            return getITelephony().getCdmaEriIconMode();
+        } catch (RemoteException ex) {
+            // the phone process is restarting.
+            return -1;
+        }
+    }
+
+    /**
+     * Returns the CDMA ERI text,
+     *
+     * @hide
+     */
+    public String getCdmaEriText() {
+        try {
+            return getITelephony().getCdmaEriText();
+        } catch (RemoteException ex) {
+            // the phone process is restarting.
+            return null;
+        }
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index fbc596c..e78422e 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -54,34 +54,32 @@
     protected RegistrantList mIccStatusChangedRegistrants = new RegistrantList();
     protected RegistrantList mVoicePrivacyOnRegistrants = new RegistrantList();
     protected RegistrantList mVoicePrivacyOffRegistrants = new RegistrantList();
+    protected RegistrantList mOtaSessionRegistrants = new RegistrantList();
+    protected RegistrantList mCallWaitingRegistrants = new RegistrantList();
+    protected RegistrantList mInformationRecordsRegistrants = new RegistrantList();
     protected Registrant mUnsolOemHookRawRegistrant;
     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 mEmergencyCallbackModeRegistrant;
     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
+    // Network Mode received from PhoneFactory
     protected int mNetworkMode;
-    //CDMA subscription received from PhoneFactory
+    // CDMA subscription received from PhoneFactory
     protected int mCdmaSubscription;
-    //Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
+    // Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
     protected int mPhoneType;
 
 
@@ -424,6 +422,10 @@
         mIccRefreshRegistrant = new Registrant (h, what, obj);
     }
 
+    public void setEmergencyCallbackMode(Handler h, int what, Object obj) {
+        mEmergencyCallbackModeRegistrant = new Registrant (h, what, obj);
+    }
+
     public void unSetOnIccRefresh(Handler h) {
         mIccRefreshRegistrant.clear();
     }
@@ -470,6 +472,33 @@
         mUnsolOemHookRawRegistrant.clear();
     }
 
+    public void registerForOtaSessionStatus(Handler h, int what, Object obj){
+        Registrant r = new Registrant (h, what, obj);
+        mOtaSessionRegistrants.add(r);
+    }
+
+    public void unregisterForOtaSessionStatus(Handler h){
+        mOtaSessionRegistrants.remove(h);
+    }
+
+    public void registerForCdmaCallWaiting(Handler h, int what, Object obj){
+        Registrant r = new Registrant (h, what, obj);
+        mCallWaitingRegistrants.add(r);
+    }
+
+    public void unregisterForCdmaCallWaiting(Handler h){
+        mCallWaitingRegistrants.remove(h);
+    }
+
+    public void registerCdmaInformationRecord(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mInformationRecordsRegistrants.add(r);
+    }
+
+    public void unregisterCdmaInformationRecord(Handler h) {
+        mInformationRecordsRegistrants.remove(h);
+    }
+
     //***** Protected Methods
     /**
      * Store new RadioState and send notification based on the changes
diff --git a/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java b/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java
new file mode 100644
index 0000000..690df05
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CdmaInformationRecord.java
@@ -0,0 +1,201 @@
+/*
+ * 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;
+
+/**
+ * TODO(Teleca): This class was poorly implemented and didn't
+ * follow the Android coding conventions. It is now more or less
+ * follows the conventions but there is still some work, see the
+ * TODO's.
+ */
+
+
+public class CdmaInformationRecord {
+    public int messageName;
+
+    public CdmaDisplayInfoRec displayInfoRec;
+    public CdmaNumberInfoRec numberInfoRec;
+    public CdmaSignalInfoRec signalInfoRec;
+    public CdmaRedirectingNumberInfoRec redirectingNumberInfoRec;
+    public CdmaLineControlInfoRec lineControlInfoRec;
+    public CdmaT53ClirInfoRec cdmaT53ClirInfoRec;
+    public CdmaT53AudioControlInfoRec cdmaT53AudioControlInfoRec;
+
+    public static final int RIL_CDMA_DISPLAY_INFO_REC = 0;
+    public static final int RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC = 1;
+    public static final int RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC = 2;
+    public static final int RIL_CDMA_CONNECTED_NUMBER_INFO_REC = 3;
+    public static final int RIL_CDMA_SIGNAL_INFO_REC = 4;
+    public static final int RIL_CDMA_REDIRECTING_NUMBER_INFO_REC = 5;
+    public static final int RIL_CDMA_LINE_CONTROL_INFO_REC = 6;
+    public static final int RIL_CDMA_EXTENDED_DISPLAY_INFO_REC = 7;
+    public static final int RIL_CDMA_T53_CLIR_INFO_REC = 8;
+    public static final int RIL_CDMA_T53_RELEASE_INFO_REC = 9;
+    public static final int RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC = 10;
+
+    public CdmaInformationRecord(int messageName) {
+        this.messageName = messageName;
+    }
+
+    void createDisplayInfo(int length, char buffer[]) {
+        displayInfoRec = new CdmaDisplayInfoRec(length, buffer);
+    }
+
+    void createNumberInfo(int length, char buffer[]) {
+        numberInfoRec = new CdmaNumberInfoRec(length, buffer);
+    }
+
+    void createSignalInfo(char buffer[]) {
+        signalInfoRec = new CdmaSignalInfoRec(buffer);
+    }
+
+    void createRedirectingNumberInfo(int length, char buffer[], int reason) {
+        redirectingNumberInfoRec = new CdmaRedirectingNumberInfoRec(length, buffer, reason);
+    }
+
+    void createLineControlInfo(char buffer[]) {
+        lineControlInfoRec = new CdmaLineControlInfoRec(buffer);
+    }
+
+    void createT53ClirInfo(char buffer) {
+        cdmaT53ClirInfoRec = new CdmaT53ClirInfoRec(buffer);
+    }
+
+    void createT53AudioControlInfo(char ul, char dl) {
+        cdmaT53AudioControlInfoRec = new CdmaT53AudioControlInfoRec(ul, dl);
+    }
+
+    /**
+     * TODO(Teleca): Add comments for each class giving the
+     * document and section where the information is defined
+     * as shown CdmaSignalInfoRec. Also add a toString to
+     * each of these to ease debugging.
+     */
+
+    /**
+     * Signal Information record from 3GPP2 C.S005 3.7.5.5
+     */
+    public static class CdmaSignalInfoRec {
+        public boolean isPresent;   /* non-zero if signal information record is present */
+        public int signalType;
+        public int alertPitch;
+        public int signalCode;
+
+        public CdmaSignalInfoRec() {}
+
+        public CdmaSignalInfoRec(char buffer[]) {
+            isPresent = buffer[0] == 1;
+            signalType = buffer[1];
+            alertPitch = buffer[2];
+            signalCode = buffer[3];
+        }
+
+        @Override
+        public String toString() {
+            return "CdmaSignalInfo: {" +
+                    " isPresent: " + isPresent +
+                    ", signalType: " + signalType +
+                    ", alertPitch: " + alertPitch +
+                    ", signalCode: " + signalCode +
+                    " }";
+        }
+    }
+
+    public static class CdmaDisplayInfoRec {
+        public char alphaLen;
+        public char alphaBuf[];
+
+        public CdmaDisplayInfoRec(int length, char buffer[]) {
+            alphaLen = (char)length;
+            alphaBuf = new char[length];
+            for(int i = 0; i < length; i++)
+                alphaBuf[i] = buffer[i];
+        }
+    }
+
+    public static class CdmaNumberInfoRec {
+        public int len;
+        public char buf[];
+        public char numberType;
+        public char numberPlan;
+        public char pi; // TODO(Teleca): poor name, no meaning
+        public char si; // TODO(Teleca): poor name
+
+        public CdmaNumberInfoRec(int length, char buffer[]) {
+            int i;
+
+            len = length;
+            buf = new char[length];
+            for (i = 0; i < len; i++) {
+                buf[i] = buffer[i];
+            }
+
+            numberType = buffer[i++];
+            numberPlan = buffer[i++];
+            pi = buffer[i++];
+            si = buffer[i++];
+        }
+    }
+
+    public static class CdmaRedirectingNumberInfoRec {
+        public static final int REASON_UNKNOWN = 0;
+        public static final int REASON_CALL_FORWARDING_BUSY = 1;
+        public static final int REASON_CALL_FORWARDING_NO_REPLY = 2;
+        public static final int REASON_CALLED_DTE_OUT_OF_ORDER = 9;
+        public static final int REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10;
+        public static final int REASON_CALL_FORWARDING_UNCONDITIONAL = 15;
+
+        public CdmaNumberInfoRec numberInfoRec;
+        public int redirectingReason;
+
+        public CdmaRedirectingNumberInfoRec(int length, char buffer[], int reason) {
+            numberInfoRec = new CdmaNumberInfoRec(length, buffer);
+            redirectingReason = reason;
+        }
+    }
+
+    public static class CdmaLineControlInfoRec {
+        public char lineCtrlPolarityIncluded;
+        public char lineCtrlToggle;
+        public char lineCtrlReverse;
+        public char lineCtrlPowerDenial;
+
+        CdmaLineControlInfoRec(char buffer[]) {
+            lineCtrlPolarityIncluded = buffer[0];
+            lineCtrlToggle = buffer[1];
+            lineCtrlReverse = buffer[2];
+            lineCtrlPowerDenial = buffer[3];
+        }
+    }
+
+    // TODO(Teleca): A class for a single character, is this needed?
+    public static class CdmaT53ClirInfoRec {
+        public char cause;
+
+        public CdmaT53ClirInfoRec(char buffer) {
+            cause = buffer;
+        }
+    }
+
+    public static class CdmaT53AudioControlInfoRec {
+        public char uplink;
+        public char downlink;
+
+        public CdmaT53AudioControlInfoRec(char ul, char dl) {
+            uplink = ul;
+            downlink = dl;
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index 5a1bb7e..ddf6b50 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -241,6 +241,24 @@
     void unregisterForRUIMReady(Handler h);
 
     /**
+     * Registers for the status of an OTASP/OTAPA session
+     */
+    void registerForOtaSessionStatus(Handler h, int what, Object obj);
+    void unregisterForOtaSessionStatus(Handler h);
+
+    /**
+      * register for Call waiting for CDMA
+      */
+    void registerForCdmaCallWaiting(Handler h, int what, Object obj);
+    void unregisterForCdmaCallWaiting(Handler h);
+
+    /**
+     * Registers for CDMA information records
+     */
+    void registerCdmaInformationRecord(Handler h, int what, Object obj);
+    void unregisterCdmaInformationRecord(Handler h);
+
+    /**
      * unlike the register* methods, there's only one new SMS handler
      * if you need to unregister, you should also tell the radio to stop
      * sending SMS's to you (via AT+CNMI)
@@ -326,6 +344,16 @@
     void unSetOnIccSmsFull(Handler h);
 
     /**
+     * Sets the handler for Emergency call-back Mode enter mesage.
+     * 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 setEmergencyCallbackMode(Handler h, int what, Object obj);
+
+    /**
      * Sets the handler for SIM Refresh notifications.
      * Unlike the register* methods, there's only one notification handler
      *
@@ -348,12 +376,12 @@
     void unSetOnCallRing(Handler h);
 
     /**
-     * Sets the handler for RESTRICTED_STATE changed notification, 
+     * Sets the handler for RESTRICTED_STATE changed notification,
      * eg, for Domain Specific Access Control
      * unlike the register* methods, there's only one signal strength handler
-     * 
-     * AsyncResult.result is an int[1]     
-     * response.obj.result[0] is a bitmask of RIL_RESTRICTED_STATE_* values 
+     *
+     * AsyncResult.result is an int[1]
+     * response.obj.result[0] is a bitmask of RIL_RESTRICTED_STATE_* values
      */
 
     void setOnRestrictedStateChanged(Handler h, int what, Object obj);
@@ -516,7 +544,7 @@
      *  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
+     *  ar.result contains a List of DataCallState
      *  @deprecated
      */
     void getPDPContextList(Message result);
@@ -526,7 +554,7 @@
      *  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
+     *  ar.result contains a List of DataCallState
      */
     void getDataCallList(Message result);
 
@@ -767,6 +795,12 @@
      */
     void stopDtmf(Message result);
 
+    /**
+     *  ar.exception carries exception on failure
+     *  ar.userObject contains the orignal value of result.obj
+     *  ar.result is null on success and failure
+     */
+    void sendBurstDtmf(String dtmfString, Message result);
 
     /**
      * smscPDU is smsc address in PDU form GSM BCD format prefixed
@@ -1087,13 +1121,12 @@
     public void getDeviceIdentity(Message response);
 
     /**
-     * Request the device IMSI_M / MDN / AH_SID / H_SID / H_NID.
+     * Request the device MDN / H_SID / H_NID / MIN.
      * "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
+     *   [0] is MDN if CDMA subscription is available
+     *   [1] is H_SID (Home SID) if CDMA subscription is available
+     *   [2] is H_NID (Home NID) if CDMA subscription is available
+     *   [3] is MIN (10 digits, MIN2+MIN1) if CDMA subscription is available
      */
     public void getCDMASubscription(Message response);
 
@@ -1133,7 +1166,7 @@
      * @param enable is true to enable, false to disable
      * @param response is callback message
      */
-    void setTTYModeEnabled(boolean enable, Message response);
+    void setTTYMode(int ttyMode, Message response);
 
     /**
      *  Query the TTY mode for the CDMA phone
@@ -1142,7 +1175,7 @@
      *
      * @param response is callback message
      */
-    void queryTTYModeEnabled(Message response);
+    void queryTTYMode(Message response);
 
     /**
      * Setup a packet data connection On successful completion, the result
@@ -1196,6 +1229,10 @@
      * @param result
      *            Callback message is empty on completion
      */
+    /**
+     * TODO(Teleca): configValuesArray is represented as a RIL_BroadcastSMSConfig
+     * so we think this should be a class with the appropriate parameters not an array?
+     */
     public void setCdmaBroadcastConfig(int[] configValuesArray, Message result);
 
     /**
@@ -1205,4 +1242,10 @@
      *            Callback message contains the configuration from the modem on completion
      */
     public void getCdmaBroadcastConfig(Message result);
+
+    /**
+     * Requests the radio's system selection module to exit emergency callback mode.
+     * @param response callback message
+     */
+    public void exitEmergencyCallbackMode(Message response);
 }
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index 86ceb89..c6bbf82 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -29,25 +29,34 @@
 
     
     public enum DisconnectCause {
-        NOT_DISCONNECTED,   /* has not yet disconnected */
-        INCOMING_MISSED,    /* an incoming call that was missed and never answered */
-        NORMAL,             /* normal; remote */
-        LOCAL,              /* normal; local hangup */
-        BUSY,               /* outgoing call to busy line */
-        CONGESTION,         /* outgoing call to congested network */
-        MMI,                /* not presently used; dial() returns null */
-        INVALID_NUMBER,     /* invalid dial string */
+        NOT_DISCONNECTED,               /* has not yet disconnected */
+        INCOMING_MISSED,                /* an incoming call that was missed and never answered */
+        NORMAL,                         /* normal; remote */
+        LOCAL,                          /* normal; local hangup */
+        BUSY,                           /* outgoing call to busy line */
+        CONGESTION,                     /* outgoing call to congested network */
+        MMI,                            /* not presently used; dial() returns null */
+        INVALID_NUMBER,                 /* invalid dial string */
         LOST_SIGNAL,
-        LIMIT_EXCEEDED,     /* eg GSM ACM limit exceeded */
-        INCOMING_REJECTED,  /* an incoming call that was rejected */
-        POWER_OFF,          /* radio is turned off explicitly */
-        OUT_OF_SERVICE,     /* out of service */
-        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 */
-        CS_RESTRICTED_NORMAL,/* call was blocked by restricted normal voice access */
-        CS_RESTRICTED_EMERGENCY/* call was blocked by restricted emergency voice access */
+        LIMIT_EXCEEDED,                 /* eg GSM ACM limit exceeded */
+        INCOMING_REJECTED,              /* an incoming call that was rejected */
+        POWER_OFF,                      /* radio is turned off explicitly */
+        OUT_OF_SERVICE,                 /* out of service */
+        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 */
+        CS_RESTRICTED_NORMAL,           /* call was blocked by restricted normal voice access */
+        CS_RESTRICTED_EMERGENCY,        /* call was blocked by restricted emergency voice access */
+        CDMA_LOCKED_UNTIL_POWER_CYCLE,  /* MS is locked until next power cycle */
+        CDMA_DROP,
+        CDMA_INTERCEPT,                 /* INTERCEPT order received, MS state idle entered */
+        CDMA_REORDER,                   /* MS has been redirected, call is cancelled */
+        CDMA_SO_REJECT,                 /* service option rejection */
+        CDMA_RETRY_ORDER,               /* requeseted service is rejected, retry delay is set */
+        CDMA_ACCESS_FAILURE,
+        CDMA_PREEMPTED,
+        CDMA_NOT_EMERGENCY              /* not an emergency call */
     }
 
     Object userData;
diff --git a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
similarity index 63%
rename from telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
rename to telephony/java/com/android/internal/telephony/DataCallState.java
index 31cdacf..d0f3d24 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
+ * 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,25 +15,18 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-/**
- * {@hide}
- */
-public class PDPContextState {
+public class DataCallState {
     public int cid;
     public int active;
     public String type;
     public String apn;
     public String address;
 
+    @Override
     public String toString() {
-        return "com.android.internal.telephony.gsm.PDPContextState: {" +
-               " cid: " + cid +
-               ", active: " + active +
-               ", type: " + type +
-               ", apn: " + apn +
-               ", address: " + address +
-               " }";
+        return "DataCallState: {" + " cid: " + cid + ", active: " + active + ", type: " + type
+                + ", apn: " + apn + ", address: " + address + " }";
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 5b826b2..d23af1f 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -63,7 +63,8 @@
         NONE,
         DATAIN,
         DATAOUT,
-        DATAINANDOUT
+        DATAINANDOUT,
+        DORMANT
     }
 
     //***** Event Codes
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 79b4afe..d6151c6 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -62,7 +62,7 @@
 
     public void notifySignalStrength(Phone sender) {
         try {
-            mRegistry.notifySignalStrength(sender.getSignalStrengthASU());
+            mRegistry.notifySignalStrength(sender.getSignalStrength());
         } catch (RemoteException ex) {
             // system process is dead
         }
@@ -200,6 +200,8 @@
                 return TelephonyManager.DATA_ACTIVITY_OUT;
             case DATAINANDOUT:
                 return TelephonyManager.DATA_ACTIVITY_INOUT;
+            case DORMANT:
+                return TelephonyManager.DATA_ACTIVITY_DORMANT;
             default:
                 return TelephonyManager.DATA_ACTIVITY_NONE;
         }
@@ -217,6 +219,8 @@
                 return Phone.DataActivityState.DATAOUT;
             case TelephonyManager.DATA_ACTIVITY_INOUT:
                 return Phone.DataActivityState.DATAINANDOUT;
+            case TelephonyManager.DATA_ACTIVITY_DORMANT:
+                return Phone.DataActivityState.DORMANT;
             default:
                 return Phone.DataActivityState.NONE;
         }
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index e0884b3..0202ec8 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 
 oneway interface IPhoneStateListener {
     void onServiceStateChanged(in ServiceState serviceState);
@@ -30,5 +31,6 @@
     void onCallStateChanged(int state, String incomingNumber);
     void onDataConnectionStateChanged(int state);
     void onDataActivity(int direction);
+    void onSignalStrengthsChanged(in SignalStrength signalStrength);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bab0603..cc6b452 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -221,5 +221,22 @@
      */
     int getActivePhoneType();
 
+    /**
+     * Returns the CDMA ERI icon index to display
+     */
+    int getCdmaEriIconIndex();
+
+    /**
+     * Returns the CDMA ERI icon mode,
+     * 0 - ON
+     * 1 - FLASHING
+     */
+    int getCdmaEriIconMode();
+
+    /**
+     * Returns the CDMA ERI text,
+     */
+    String getCdmaEriText();
+
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 1b011fe..865c6ca 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import com.android.internal.telephony.IPhoneStateListener;
 
 interface ITelephonyRegistry {
@@ -26,7 +27,7 @@
 
     void notifyCallState(int state, String incomingNumber);
     void notifyServiceState(in ServiceState state);
-    void notifySignalStrength(int signalStrengthASU);
+    void notifySignalStrength(in SignalStrength signalStrength);
     void notifyMessageWaitingChanged(boolean mwi);
     void notifyCallForwardingChanged(boolean cfi);
     void notifyDataActivity(int state);
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index 014fbb6..7eafafd 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -61,4 +61,5 @@
     static final String DF_TELECOM = "7F10";
     static final String DF_GRAPHICS = "5F50";
     static final String DF_GSM = "7F20";
+    static final String DF_CDMA = "7F25";
 }
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 03c1c56..b5f2afe 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -23,6 +23,7 @@
 import android.preference.PreferenceManager;
 import android.telephony.CellLocation;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.gsm.NetworkInfo;
@@ -82,9 +83,11 @@
          * <li>DATAIN = Receiving IP ppp traffic</li>
          * <li>DATAOUT = Sending IP ppp traffic</li>
          * <li>DATAINANDOUT = Both receiving and sending IP ppp traffic</li>
+         * <li>DORMANT = The data connection is still active,
+                                     but physical link is down</li>
          * </ul>
          */
-        NONE, DATAIN, DATAOUT, DATAINANDOUT;
+        NONE, DATAIN, DATAOUT, DATAINANDOUT, DORMANT;
     };
 
     enum SuppService {
@@ -150,7 +153,7 @@
     static final String REASON_PS_RESTRICT_ENABLED = "psRestrictEnabled";
     static final String REASON_PS_RESTRICT_DISABLED = "psRestrictDisabled";
     static final String REASON_SIM_LOADED = "simLoaded";
-    
+
     // Used for band mode selection methods
     static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
     static final int BM_EURO_BAND   = 1; // GSM-900 / DCS-1800 / WCDMA-IMT-2000
@@ -162,28 +165,35 @@
 
     // Used for preferred network type
     // 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;
+    static final int NT_MODE_WCDMA_PREF   = 0; /* GSM/WCDMA (WCDMA preferred) */
+    static final int NT_MODE_GSM_ONLY     = 1; /* GSM only */
+    static final int NT_MODE_WCDMA_ONLY   = 2; /* WCDMA only */
+    static final int NT_MODE_GSM_UMTS     = 3; /* GSM/WCDMA (auto mode, according to PRL)
+                                                  AVAILABLE Application Settings menu */
+    static final int NT_MODE_CDMA         = 4; /* CDMA and EvDo (auto mode, according to PRL)
+                                                  AVAILABLE Application Settings menu */
+    static final int NT_MODE_CDMA_NO_EVDO = 5; /* CDMA only */
+    static final int NT_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
+    static final int NT_MODE_GLOBAL       = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according
+                                                  to PRL) AVAILABLE Application Settings menu */
+    static final int PREFERRED_NT_MODE    = NT_MODE_GLOBAL;
 
 
     // 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
+    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
+    static final int CDMA_SUBSCRIPTION_RUIM_SIM = 0; // RUIM/SIM (default)
+    static final int CDMA_SUBSCRIPTION_NV       = 1; // NV -> non-volatile memory
+
+    static final int PREFERRED_CDMA_SUBSCRIPTION = CDMA_SUBSCRIPTION_NV;
+
+    static final int TTY_MODE_OFF = 0;
+    static final int TTY_MODE_FULL = 1;
+    static final int TTY_MODE_HCO = 2;
+    static final int TTY_MODE_VCO = 3;
 
     /**
      * Get the current ServiceState. Use
@@ -263,16 +273,11 @@
     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).
-     * 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>
+     * Get current signal strength.
      *
-     * @return Current signal strength in ASU's.
+     * @return Current signal strength as SignalStrength
      */
-    int getSignalStrengthASU();
+    SignalStrength getSignalStrength();
 
     /**
      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
@@ -494,6 +499,53 @@
     void unregisterForInCallVoicePrivacyOff(Handler h);
 
     /**
+     * Register for notifications about information record available
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    void registerCdmaInformationRecord(Handler h, int what, Object obj);
+
+    /**
+     * Unregister for notifications about information record available
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    void unregisterCdmaInformationRecord(Handler h);
+
+    /**
+     * Register for the indication of OTA status change
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    void registerForOtaStatusChange(Handler h, int what, Object obj);
+
+    /**
+     * Unregister for the indication of OTA status change
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    void unregisterForOtaStatusChange(Handler h);
+
+    /**
+     * Register for the indication of Cdma Call Waiting
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    void registerForCdmaCallWaiting(Handler h, int what, Object obj);
+
+    /**
+     * Unregister for the indication of Cdma Call Waiting
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    void unregisterForCdmaCallWaiting(Handler h);
+    /**
      * Returns SIM record load state. Use
      * <code>getSimCard().registerForReady()</code> for change notification.
      *
@@ -707,6 +759,10 @@
      */
     void stopDtmf();
 
+    /**
+     * Play a Burst of DTMF tone on the active call. Ignored if there is no active call.
+     */
+    void sendBurstDtmf(String dtmfString);
 
     /**
      * Sets the radio power on/off state (off is sometimes
@@ -1279,6 +1335,10 @@
 
     //***** CDMA support methods
 
+    /**
+     * Retrieves the MIN for CDMA phones.
+     */
+    String getMin();
 
     /**
      * Retrieves the ESN for CDMA phones.
@@ -1306,22 +1366,30 @@
     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager();
 
     /**
-     * setTTYModeEnabled
+     * setTTYMode
      * 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);
+    void setTTYMode(int ttyMode, Message onComplete);
 
     /**
-     * queryTTYModeEnabled
+     * queryTTYMode
      * query the status of the TTY mode
      *
      * @param onComplete a callback message when the action is completed.
      */
-    void queryTTYModeEnabled(Message onComplete);
+    void queryTTYMode(Message onComplete);
+
+    /**
+     * exitEmergencyCallbackMode
+     * exits the emergency callback mode
+     *
+     * @param onComplete a callback message when the action is completed.
+     */
+    void exitEmergencyCallbackMode(Message onComplete);
 
     /**
      * Activate or deactivate cell broadcast SMS.
@@ -1344,10 +1412,30 @@
     /**
      * Configure cell broadcast SMS.
      *
+     * TODO: Change the configValuesArray to a RIL_BroadcastSMSConfig
+     *
      * @param response
      *            Callback message is empty on completion
      */
     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response);
 
     public void notifyDataActivity();
+
+    /**
+     * Returns the CDMA ERI icon index to display
+     */
+    public int getCdmaEriIconIndex();
+
+    /**
+     * Returns the CDMA ERI icon mode,
+     * 0 - ON
+     * 1 - FLASHING
+     */
+    public int getCdmaEriIconMode();
+
+    /**
+     * Returns the CDMA ERI text,
+     */
+    public String getCdmaEriText();
+
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 0314034..7234aa3 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -29,6 +29,7 @@
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -52,6 +53,15 @@
  *
  */
 
+/**
+ * TODO(Teleca): This has a multitude of methods that are CDMA specific
+ * , (registerForVoicePrivacy, registerCdmaInformationRecord, registerCdmaCallWaiting,
+ * setCdmaRoamingPreference, setCdmaSubscription, getCdmaEriIcon, getCdmaEriText, ...) can
+ * these type of calls be more abstract. For example CallWaiting is common between the GSM/CDMA
+ * it would seem that doesn't need to be cdma specific. Also, should the application be directly
+ * dealing with the CdmaInformationRecord's could they be abstracted to something more generic.
+ */
+
 public abstract class PhoneBase implements Phone {
     private static final String LOG_TAG = "PHONE";
     private static final boolean LOCAL_DEBUG = true;
@@ -90,6 +100,8 @@
     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;
+    protected static final int EVENT_CDMA_CALL_WAITING              = 24;
+    protected static final int EVENT_EMERGENCY_CALLBACK_MODE        = 25;
 
     // Key used to read/write current CLIR setting
     public static final String CLIR_KEY = "clir_key";
@@ -187,7 +199,7 @@
         setUnitTestMode(unitTestMode);
 
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
-        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);        
+        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
     }
 
     // Inherited documentation suffices.
@@ -204,7 +216,7 @@
         mDnsCheckDisabled = b;
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor editor = sp.edit();
-        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);        
+        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
         editor.commit();
     }
 
@@ -282,6 +294,35 @@
         mCM.unregisterForInCallVoicePrivacyOff(h);
     }
 
+    // Inherited documentation suffices.
+    public void registerForOtaStatusChange(Handler h, int what, Object obj){
+        mCM.registerForOtaSessionStatus(h,what,obj);
+    }
+
+    // Inherited documentation suffices.
+    public void unregisterForOtaStatusChange(Handler h){
+        mCM.unregisterForOtaSessionStatus(h);
+    }
+
+    // Inherited documentation suffices.
+    public void registerCdmaInformationRecord(Handler h, int what, Object obj){
+        mCM.registerCdmaInformationRecord(h,what,obj);
+    }
+
+    // Inherited documentation suffices.
+    public void unregisterCdmaInformationRecord(Handler h){
+        mCM.unregisterCdmaInformationRecord(h);
+    }
+
+    // Inherited documentation suffices.
+    public void registerForCdmaCallWaiting(Handler h, int what, Object obj){
+        mCM.registerForCdmaCallWaiting(h,what,obj);
+    }
+
+    // Inherited documentation suffices.
+    public void unregisterForCdmaCallWaiting(Handler h){
+        mCM.unregisterForCdmaCallWaiting(h);
+    }
 
     /**
      * Notifiy registrants of a new ringing Connection.
@@ -567,9 +608,6 @@
         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);
     }
@@ -582,12 +620,20 @@
         mCM.setSmscAddress(address, result);
     }
 
-    public void setTTYModeEnabled(boolean enable, Message onComplete) {
+    public void setTTYMode(int ttyMode, 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) {
+    public void queryTTYMode(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.");
+    }
+
+    /**
+     *  Send the exit emergency callback mode message
+     */
+    public void exitEmergencyCallbackMode(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.");
     }
@@ -638,4 +684,30 @@
 
     public abstract String getPhoneName();
 
+    /**
+     * Returns the CDMA ERI icon index to display
+     */
+    public int getCdmaEriIconIndex() {
+        Log.e(LOG_TAG, "Error! getCdmaEriIconIndex should never be executed in GSM mode");
+        return -1;
+    }
+
+    /**
+     * Returns the CDMA ERI icon mode,
+     * 0 - ON
+     * 1 - FLASHING
+     */
+    public int getCdmaEriIconMode() {
+        Log.e(LOG_TAG, "Error! getCdmaEriIconMode should never be executed in GSM mode");
+        return -1;
+    }
+
+    /**
+     * Returns the CDMA ERI text,
+     */
+    public String getCdmaEriText() {
+        Log.e(LOG_TAG, "Error! getCdmaEriText should never be executed in GSM mode");
+        return "GSM nw, no ERI";
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 86e2f04..3beb60a 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -108,23 +108,26 @@
                 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;
+                    case RILConstants.NETWORK_MODE_CDMA:
+                    case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+                    case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+                        sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating CDMAPhone");
+                        break;
+                    case RILConstants.NETWORK_MODE_GLOBAL:
+                    default:
+                        sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating CDMAPhone");
                 }
                 sMadeDefaults = true;
             }
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index b76d801..a329cbb 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -26,6 +26,7 @@
 import android.preference.PreferenceManager;
 import android.telephony.CellLocation;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.util.Log;
 
 import com.android.internal.telephony.cdma.CDMAPhone;
@@ -127,10 +128,9 @@
             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: "
+            Log.e(LOG_TAG,"Error! This handler was not registered for this message type. Message: "
                     + msg.what);
         break;
         }
@@ -198,8 +198,8 @@
         return mActivePhone.getActiveApn();
     }
 
-    public int getSignalStrengthASU() {
-        return mActivePhone.getSignalStrengthASU();
+    public SignalStrength getSignalStrength() {
+        return mActivePhone.getSignalStrength();
     }
 
     public void registerForUnknownConnection(Handler h, int what, Object obj) {
@@ -306,6 +306,30 @@
         mActivePhone.unregisterForInCallVoicePrivacyOff(h);
     }
 
+    public void registerCdmaInformationRecord(Handler h, int what, Object obj) {
+        mActivePhone.registerCdmaInformationRecord(h,what,obj);
+    }
+
+    public void unregisterCdmaInformationRecord(Handler h) {
+        mActivePhone.unregisterCdmaInformationRecord(h);
+    }
+
+    public void registerForOtaStatusChange(Handler h, int what, Object obj){
+        mActivePhone.registerForOtaStatusChange(h,what,obj);
+    }
+
+    public void unregisterForOtaStatusChange(Handler h){
+        mActivePhone.unregisterForOtaStatusChange(h);
+    }
+
+    public void registerForCdmaCallWaiting(Handler h, int what, Object obj){
+        mActivePhone.registerForCdmaCallWaiting(h,what,obj);
+    }
+
+    public void unregisterForCdmaCallWaiting(Handler h){
+        mActivePhone.unregisterForCdmaCallWaiting(h);
+    }
+
     public boolean getIccRecordsLoaded() {
         return mActivePhone.getIccRecordsLoaded();
     }
@@ -390,6 +414,10 @@
         mActivePhone.stopDtmf();
     }
 
+    public void sendBurstDtmf(String dtmfString) {
+        mActivePhone.sendBurstDtmf(dtmfString);
+    }
+
     public void setRadioPower(boolean power) {
         mActivePhone.setRadioPower(power);
     }
@@ -628,6 +656,10 @@
         return mActivePhone.getIccSerialNumber();
     }
 
+    public String getMin() {
+        return mActivePhone.getMin();
+    }
+
     public String getEsn() {
         return mActivePhone.getEsn();
     }
@@ -648,12 +680,16 @@
         return mActivePhone.getIccPhoneBookInterfaceManager();
     }
 
-    public void setTTYModeEnabled(boolean enable, Message onComplete) {
-        mActivePhone.setTTYModeEnabled(enable, onComplete);
+    public void setTTYMode(int ttyMode, Message onComplete) {
+        mActivePhone.setTTYMode(ttyMode, onComplete);
     }
 
-    public void queryTTYModeEnabled(Message onComplete) {
-        mActivePhone.queryTTYModeEnabled(onComplete);
+    public void queryTTYMode(Message onComplete) {
+        mActivePhone.queryTTYMode(onComplete);
+    }
+
+    public void exitEmergencyCallbackMode(Message onComplete) {
+        mActivePhone.exitEmergencyCallbackMode(onComplete);
     }
 
     public void activateCellBroadcastSms(int activate, Message response) {
@@ -679,5 +715,17 @@
     public void setSmscAddress(String address, Message result) {
         mActivePhone.setSmscAddress(address, result);
     }
+
+    public int getCdmaEriIconIndex() {
+         return mActivePhone.getCdmaEriIconIndex();
+    }
+
+    public int getCdmaEriIconMode() {
+         return mActivePhone.getCdmaEriIconMode();
+    }
+
+    public String getCdmaEriText() {
+         return mActivePhone.getCdmaEriText();
+    }
 }
 
diff --git a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
index fd822cd..b31161c 100644
--- a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
+++ b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
@@ -23,6 +23,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
@@ -39,8 +40,6 @@
     private static final String LOG_TAG = "PHONE";
     private static final boolean DBG = false;
 
-    public static final String INTENT_KEY_ASU = "asu";
-
     private static final int NOTIF_PHONE    = 1 << 0;
     private static final int NOTIF_SERVICE  = 1 << 1;
     private static final int NOTIF_SIGNAL   = 1 << 2;
@@ -49,7 +48,8 @@
 
     Phone.State mPhoneState = Phone.State.IDLE;
     ServiceState mServiceState = new ServiceState();
-    int mAsu  = -1;
+    SignalStrength mSignalStrength = new SignalStrength();
+
     private Context mContext;
     private Handler mTarget;
     private IntentFilter mFilter;
@@ -106,12 +106,14 @@
      * Throws RuntimeException if client has not called notifySignalStrength()
      */
     public int getSignalStrength() {
+        // TODO: use new SignalStrength instead of asu
         if ((mWants & NOTIF_SIGNAL) == 0) {
             throw new RuntimeException
                 ("client must call notifySignalStrength(int)");
         }
+        int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
 
-        return mAsu;
+        return (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
     }
 
     /**
@@ -129,10 +131,15 @@
 
         int dBm = -1;
 
-        if (mAsu != -1) {
-            dBm = -113 + 2*mAsu;
+        if(!mSignalStrength.isGsm()) {
+            dBm = mSignalStrength.getCdmaDbm();
+        } else {
+            int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
+            int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
+            if (asu != -1) {
+                dBm = -113 + 2*asu;
+            }
         }
-
         return dBm;
     }
 
@@ -180,8 +187,7 @@
 
         try {
             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);
+                mSignalStrength = SignalStrength.newFromBundle(intent.getExtras());
 
                 if (mTarget != null && getNotifySignalStrength()) {
                     Message message = Message.obtain(mTarget, mAsuEventWhat);
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index be18a39..04e33fe 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -38,8 +38,10 @@
 import android.util.Config;
 import android.util.Log;
 
+import com.android.internal.telephony.CdmaInformationRecord;
+import com.android.internal.telephony.cdma.CdmaCallWaiting;
+import com.android.internal.telephony.DataCallState;
 import com.android.internal.telephony.gsm.NetworkInfo;
-import com.android.internal.telephony.gsm.PDPContextState;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 
 import java.io.ByteArrayInputStream;
@@ -233,6 +235,7 @@
     private static final int CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES = 31;
 
     BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
         public void onReceive(Context context, Intent intent) {
             if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                 sendScreenState(true);
@@ -562,18 +565,22 @@
         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;
+                break;
+            case RILConstants.NETWORK_MODE_CDMA:
+            case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+            case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+                mPhoneType = RILConstants.CDMA_PHONE;
+                break;
+            case RILConstants.NETWORK_MODE_GLOBAL:
+                mPhoneType = RILConstants.CDMA_PHONE;
+                break;
+            default:
+                mPhoneType = RILConstants.CDMA_PHONE;
         }
 
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
@@ -1052,6 +1059,16 @@
         send(rr);
     }
 
+    public void
+    sendBurstDtmf(String dtmfString, Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BURST_DTMF, result);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        rr.mp.writeString(dtmfString);
+
+        send(rr);
+    }
 
     public void
     sendSMS (String smscPDU, String pdu, Message result) {
@@ -1361,6 +1378,7 @@
         if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest)
                 + " 0x" + Integer.toHexString(command)
                 + " 0x" + Integer.toHexString(fileid) + " "
+                + " path: " + path + ","
                 + p1 + "," + p2 + "," + p3);
 
         send(rr);
@@ -1793,7 +1811,8 @@
         rr.mp.writeInt(1);
         rr.mp.writeInt(on ? 1 : 0);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ": " + on);
+        if (RILJ_LOGD) riljLog(rr.serialString()
+                + "> " + requestToString(rr.mRequest) + ": " + on);
 
         send(rr);
     }
@@ -2055,6 +2074,7 @@
             case RIL_REQUEST_DEVICE_IDENTITY: ret =  responseStrings(p); break;
             case RIL_REQUEST_GET_SMSC_ADDRESS: ret = responseString(p); break;
             case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break;
+            case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
             default:
                 throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
             //break;
@@ -2176,13 +2196,18 @@
             case RIL_UNSOL_STK_CALL_SETUP: ret = responseInts(p); break;
             case RIL_UNSOL_SIM_SMS_STORAGE_FULL: ret =  responseVoid(p); break;
             case RIL_UNSOL_SIM_REFRESH: ret =  responseInts(p); break;
-            case RIL_UNSOL_CALL_RING: ret =  responseVoid(p); break;
+            case RIL_UNSOL_CALL_RING: ret =  responseCallRing(p); break;
             case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break;
             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;
+            case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
+            case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break;
+            case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break;
+            case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;
             case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
+
             default:
                 throw new RuntimeException("Unrecognized unsol response: " + response);
             //break; (implied)
@@ -2415,6 +2440,39 @@
                     mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));
                 }
                 break;
+
+            case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE:
+                if (RILJ_LOGD) unsljLog(response);
+
+                if (mEmergencyCallbackModeRegistrant != null) {
+                    mEmergencyCallbackModeRegistrant.notifyRegistrant();
+                }
+                break;
+
+            case RIL_UNSOL_CDMA_CALL_WAITING:
+                if (RILJ_LOGD) unsljLog(response);
+
+                if(mCallWaitingRegistrants != null) {
+                    mCallWaitingRegistrants.notifyRegistrants(new AsyncResult (null, ret, null));
+                }
+                break;
+
+            case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS:
+                if (RILJ_LOGD) unsljLog(response);
+
+                if (mOtaSessionRegistrants != null) {
+                    mOtaSessionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
+                }
+                break;
+
+            case RIL_UNSOL_CDMA_INFO_REC:
+                if (RILJ_LOGD)
+                    unsljLog(response);
+                if (mInformationRecordsRegistrants != null) {
+                    mInformationRecordsRegistrants.notifyRegistrants(new AsyncResult(null, ret,
+                            null));
+                }
+                break;
         }
     }
 
@@ -2547,6 +2605,11 @@
 
         String s = p.readString();
 
+        if (RILJ_LOGD) riljLog("< iccIO: "
+                + " 0x" + Integer.toHexString(sw1)
+                + " 0x" + Integer.toHexString(sw2) + " "
+                + s);
+
         return new IccIoResult(sw1, sw2, s);
     }
 
@@ -2677,14 +2740,14 @@
 
             response.add(dc);
 
-            if ( RILConstants.CDMA_VOICE_PRIVACY == voiceSettings ) {
+            if ( RILConstants.CDMA_VOICE_PRIVACY == voicePrivacy ) {
                 mVoicePrivacyOnRegistrants.notifyRegistrants();
                 Log.d(LOG_TAG, "InCall VoicePrivacy is enabled: " +
-                        Integer.toString(voiceSettings));
+                        Integer.toString(voicePrivacy));
             } else {
                 mVoicePrivacyOffRegistrants.notifyRegistrants();
                 Log.d(LOG_TAG, "InCall VoicePrivacy is disabled: " +
-                        Integer.toString(voiceSettings));
+                        Integer.toString(voicePrivacy));
             }
         }
 
@@ -2696,21 +2759,21 @@
     private Object
     responseDataCallList(Parcel p) {
         int num;
-        ArrayList<PDPContextState> response;
+        ArrayList<DataCallState> response;
 
         num = p.readInt();
-        response = new ArrayList<PDPContextState>(num);
+        response = new ArrayList<DataCallState>(num);
 
         for (int i = 0; i < num; i++) {
-            PDPContextState pdp = new PDPContextState();
+            DataCallState dataCall = new DataCallState();
 
-            pdp.cid = p.readInt();
-            pdp.active = p.readInt();
-            pdp.type = p.readString();
-            pdp.apn = p.readString();
-            pdp.address = p.readString();
+            dataCall.cid = p.readInt();
+            dataCall.active = p.readInt();
+            dataCall.type = p.readString();
+            dataCall.apn = p.readString();
+            dataCall.address = p.readString();
 
-            response.add(pdp);
+            response.add(dataCall);
         }
 
         return response;
@@ -2771,42 +2834,135 @@
 
     private Object
     responseCDMA_BR_CNF(Parcel p) {
-        int numServiceCategories;
+        int numInts;
         int response[];
 
-        numServiceCategories = p.readInt();
+        numInts = 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];
+        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();
-             }
+        response[0] = numInts;
+        for (int i = 1 ; i < numInts; i++) {
+            response[i] = p.readInt();
         }
 
         return response;
     }
 
+    private Object
+    responseCdmaInformationRecord(Parcel p){
+
+        int num;
+        ArrayList<CdmaInformationRecord> response;
+
+        num = p.readInt();
+
+        response = new ArrayList<CdmaInformationRecord>(num);
+
+        for (int i = 0; i < num; i++) {
+            int name = p.readInt();
+            CdmaInformationRecord InfoRec = new CdmaInformationRecord(name);
+
+            char buffer[];
+            int length;
+            switch (name) {
+                case CdmaInformationRecord.RIL_CDMA_DISPLAY_INFO_REC:
+                case CdmaInformationRecord.RIL_CDMA_EXTENDED_DISPLAY_INFO_REC:
+                    length = p.readInt();
+                    buffer = new char[length];
+                    for (int j = 0; j < length; j++) {
+                        buffer[j] = (char)p.readInt();
+                    }
+                    InfoRec.createDisplayInfo(length, buffer);
+                    break;
+
+                case CdmaInformationRecord.RIL_CDMA_CALLED_PARTY_NUMBER_INFO_REC:
+                case CdmaInformationRecord.RIL_CDMA_CALLING_PARTY_NUMBER_INFO_REC:
+                case CdmaInformationRecord.RIL_CDMA_CONNECTED_NUMBER_INFO_REC:
+                    length = p.readInt();
+                    buffer = new char[length + 4];
+                    for (int j = 0; j < (length + 4); j++) {
+                        buffer[j] = (char)p.readInt();
+                    }
+                    InfoRec.createNumberInfo(length, buffer);
+                    break;
+
+                case CdmaInformationRecord.RIL_CDMA_SIGNAL_INFO_REC:
+                    buffer = new char[4];
+                    for (int j = 0; j < 4; j++) {
+                        buffer[j] = (char)p.readInt();
+                    }
+                    InfoRec.createSignalInfo(buffer);
+                    break;
+
+                case CdmaInformationRecord.RIL_CDMA_REDIRECTING_NUMBER_INFO_REC:
+                    length = p.readInt();
+                    buffer = new char[length + 4];
+                    int reason;
+                    for (int j = 0; j < (length + 4); j++) {
+                        buffer[j] = (char)p.readInt();
+                    }
+                    reason = p.readInt();
+                    InfoRec.createRedirectingNumberInfo(length, buffer, reason);
+                    break;
+
+                case CdmaInformationRecord.RIL_CDMA_LINE_CONTROL_INFO_REC:
+                    buffer = new char[4];
+                    for (int j = 0; j < 4; j++) {
+                        buffer[j] = (char)p.readInt();
+                    }
+                    InfoRec.createLineControlInfo(buffer);
+                    break;
+
+                case CdmaInformationRecord.RIL_CDMA_T53_CLIR_INFO_REC:
+                    char ch = (char)p.readInt();
+                    InfoRec.createT53ClirInfo(ch);
+                    break;
+
+                case CdmaInformationRecord.RIL_CDMA_T53_RELEASE_INFO_REC:
+                    break;
+
+                case CdmaInformationRecord.RIL_CDMA_T53_AUDIO_CONTROL_INFO_REC:
+                    char ul = (char)p.readInt();
+                    char dl = (char)p.readInt();
+                    InfoRec.createT53AudioControlInfo(ul, dl);
+                    break;
+
+                default:
+                    break;
+            }
+            response.add(InfoRec);
+        }
+
+        return response;
+    }
+
+    private Object
+    responseCdmaCallWaiting(Parcel p){
+        CdmaCallWaiting response = new CdmaCallWaiting();
+        response.number = p.readString();
+        response.numberPresentation = p.readInt();
+        response.name = p.readString();
+        response.signalInfoRecord.isPresent =  p.readInt() == 0 ? false : true;
+        response.signalInfoRecord.signalType = p.readInt();
+        response.signalInfoRecord.alertPitch = p.readInt();
+        response.signalInfoRecord.signalCode = p.readInt();
+
+        return response;
+    }
+
+    private Object
+    responseCallRing(Parcel p){
+        char response[] = new char[4];
+
+        response[0] = (char) p.readInt();    // isPresent
+        response[1] = (char) p.readInt();    // signalType
+        response[2] = (char) p.readInt();    // alertPitch
+        response[3] = (char) p.readInt();    // signal
+
+        return response;
+    }
+
     static String
     requestToString(int request) {
 /*
@@ -2915,6 +3071,7 @@
             case RIL_REQUEST_DEVICE_IDENTITY: return "RIL_REQUEST_DEVICE_IDENTITY";
             case RIL_REQUEST_GET_SMSC_ADDRESS: return "RIL_REQUEST_GET_SMSC_ADDRESS";
             case RIL_REQUEST_SET_SMSC_ADDRESS: return "RIL_REQUEST_SET_SMSC_ADDRESS";
+            case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: return "REQUEST_EXIT_EMERGENCY_CALLBACK_MODE";
             default: return "<unknown request>";
         }
     }
@@ -2949,6 +3106,14 @@
             case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";
             case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "RIL_UNSOL_RESTRICTED_STATE_CHANGED";
             case RIL_UNSOL_OEM_HOOK_RAW: return "RIL_UNSOL_OEM_HOOK_RAW";
+            case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: return "UNSOL_RESPONSE_SIM_STATUS_CHANGED";
+            case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: return "UNSOL_RESPONSE_CDMA_NEW_SMS";
+            case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: return "UNSOL_RESPONSE_NEW_BROADCAST_SMS";
+            case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL";
+            case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE";
+            case RIL_UNSOL_CDMA_CALL_WAITING: return "UNSOL_CDMA_CALL_WAITING";
+            case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: return "UNSOL_CDMA_OTA_PROVISION_STATUS";
+            case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC";
             default: return "<unknown reponse>";
         }
     }
@@ -3048,7 +3213,7 @@
     /**
      * {@inheritDoc}
      */
-    public void queryTTYModeEnabled(Message response) {
+    public void queryTTYMode(Message response) {
         RILRequest rr = RILRequest.obtain(
                 RILConstants.RIL_REQUEST_QUERY_TTY_MODE, response);
 
@@ -3058,12 +3223,12 @@
     /**
      * {@inheritDoc}
      */
-    public void setTTYModeEnabled(boolean enable, Message response) {
+    public void setTTYMode(int ttyMode, Message response) {
         RILRequest rr = RILRequest.obtain(
                 RILConstants.RIL_REQUEST_SET_TTY_MODE, response);
 
         rr.mp.writeInt(1);
-        rr.mp.writeInt(enable ? 1 : 0);
+        rr.mp.writeInt(ttyMode);
 
         send(rr);
     }
@@ -3090,11 +3255,14 @@
         send(rr);
     }
 
+    /**
+     * TODO(Teleca): configValuesArray is represented as a RIL_BroadcastSMSConfig
+     * so we think this should be a class with the appropriate parameters not an array?
+     */
     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++) {
+        for(int i = 0; i < configValuesArray.length; i++) {
             rr.mp.writeInt(configValuesArray[i]);
         }
 
@@ -3113,4 +3281,16 @@
 
         send(rr);
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void exitEmergencyCallbackMode(Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, response);
+
+        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
index bcf5141..44c863b 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -16,6 +16,13 @@
 
 package com.android.internal.telephony;
 
+/**
+ * TODO: This should probably not be an interface see
+ * http://www.javaworld.com/javaworld/javaqa/2001-06/01-qa-0608-constants.html and google with
+ * http://www.google.com/search?q=interface+constants&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a
+ *
+ * Also they should all probably be static final.
+ */
 
 /**
  * {@hide}
@@ -51,7 +58,7 @@
     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;
+    int PREFERRED_NETWORK_MODE      = NETWORK_MODE_WCDMA_PREF;
 
     /* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
     int SUBSCRIPTION_FROM_RUIM      = 0; /* CDMA subscription from RUIM when available */
@@ -67,6 +74,10 @@
     int CDM_TTY_MODE_DISABLED = 0;
     int CDM_TTY_MODE_ENABLED = 1;
 
+    int CDM_TTY_FULL_MODE = 1;
+    int CDM_TTY_HCO_MODE = 2;
+    int CDM_TTY_VCO_MODE = 3;
+
     byte CDMA_VOICE_PRIVACY = 0x70;           /* "p" value used in Ril_Call.isVoice if Privacy
                                                  is active  */
 
@@ -208,6 +219,7 @@
     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_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE = 99;
     int RIL_REQUEST_GET_SMSC_ADDRESS = 100;
     int RIL_REQUEST_SET_SMSC_ADDRESS = 101;
     int RIL_UNSOL_RESPONSE_BASE = 1000;
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 7274e99..5112ba0 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -22,6 +22,7 @@
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 
 /**
  * {@hide}
@@ -50,6 +51,8 @@
     public ServiceState ss;
     protected ServiceState newSS;
 
+    public SignalStrength mSignalStrength;
+
     // 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
@@ -104,13 +107,15 @@
     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;
+    protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA         = 28;
+    protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA          = 29;
+    protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA        = 30;
+    protected static final int EVENT_GET_LOC_DONE_CDMA                 = 31;
+    protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA       = 32;
+    protected static final int EVENT_NV_LOADED                         = 33;
+    protected static final int EVENT_POLL_STATE_CDMA_SUBSCRIPTION      = 34;
+    protected static final int EVENT_NV_READY                          = 35;
+    protected static final int EVENT_ERI_FILE_LOADED                   = 36;
 
     //***** Time Zones
     protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
@@ -142,6 +147,9 @@
         "uk", // U.K
     };
 
+    //***** Registration denied reason
+    protected static final String REGISTRATION_DENIED_GEN  = "General";
+    protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
 
     //***** Constructors
     public ServiceStateTracker() {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index c342233..91aa34e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -53,7 +53,20 @@
      */
     public static final String ACTION_RADIO_TECHNOLOGY_CHANGED 
             = "android.intent.action.RADIO_TECHNOLOGY";
-
+    /**
+     * <p>Broadcast Action: The emergency callback mode is entered.
+     *
+     * <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_EMERGENCY_CALLBACK_MODE_ENTERED
+            = "android.intent.action.EMERGENCY_CALLBACK_MODE";
     /**
      * Broadcast Action: The phone's signal strength has changed. The intent will have the
      * following extra values:</p>
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 396b42d..67ae169 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -44,6 +44,7 @@
      *  Availability: when registered to a network
      */
     static final String PROPERTY_OPERATOR_ALPHA = "gsm.operator.alpha";
+    //TODO: most of these proprieties are generic, substitute gsm. with phone. bug 1856959
 
     /** Numeric name (MCC+MNC) of current registered operator.
      *  Availability: when registered to a network
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 8ffb7ec..3f8d40c 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -16,7 +16,9 @@
 
 package com.android.internal.telephony.cdma;
 
+import android.app.ActivityManagerNative;
 import android.content.Context;
+import android.content.Intent;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
@@ -28,6 +30,7 @@
 import android.telephony.CellLocation;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -48,6 +51,7 @@
 import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.PhoneSubInfo;
 import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyIntents;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -71,8 +75,13 @@
     RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
     RuimSmsInterfaceManager mRuimSmsInterfaceManager;
     PhoneSubInfo mSubInfo;
+    EriManager mEriManager;
 
-    protected RegistrantList mNvLoadedRegistrants = new RegistrantList();
+    // mNvLoadedRegistrants are informed after the EVENT_NV_READY
+    private RegistrantList mNvLoadedRegistrants = new RegistrantList();
+
+    // mEriFileLoadedRegistrants are informed after the ERI text has been loaded
+    private RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
     private String mEsn;
     private String mMeid;
 
@@ -102,6 +111,7 @@
         mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
         mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this);
         mSubInfo = new PhoneSubInfo(this);
+        mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
 
         mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
         mRuimRecords.registerForRecordsLoaded(h, EVENT_RUIM_RECORDS_LOADED, null);
@@ -111,6 +121,9 @@
         mCM.setOnCallRing(h, EVENT_CALL_RING, null);
         mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
         mCM.registerForNVReady(h, EVENT_NV_READY, null);
+        mCM.registerForCdmaCallWaiting(h,EVENT_CDMA_CALL_WAITING,null);
+        mCM.setEmergencyCallbackMode(h, EVENT_EMERGENCY_CALLBACK_MODE, null);
+
 
         //Change the system setting
         Settings.Secure.putInt(mContext.getContentResolver(),
@@ -129,6 +142,7 @@
             mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
             mCM.unSetOnSuppServiceNotification(h);
             mCM.unSetOnCallRing(h);
+            mCM.unregisterForCdmaCallWaiting(h);
 
             //Force all referenced classes to unregister their former registered events
             mCT.dispose();
@@ -141,6 +155,7 @@
             mRuimPhoneBookInterfaceManager.dispose();
             mRuimSmsInterfaceManager.dispose();
             mSubInfo.dispose();
+            mEriManager.dispose();
         }
     }
 
@@ -155,6 +170,7 @@
             this.mDataConnection = null;
             this.mCT = null;
             this.mSST = null;
+            this.mEriManager = null;
     }
 
     protected void finalize() {
@@ -229,6 +245,10 @@
                 case DATAINANDOUT:
                     ret = DataActivityState.DATAINANDOUT;
                 break;
+
+                case DORMANT:
+                    ret = DataActivityState.DORMANT;
+                break;
             }
         }
         return ret;
@@ -261,9 +281,8 @@
         }
     }
 
-
-    public int getSignalStrengthASU() {
-        return mSST.rssi == 99 ? -1 : mSST.rssi;
+    public SignalStrength getSignalStrength() {
+        return mSST.mSignalStrength;
     }
 
     public boolean
@@ -350,6 +369,10 @@
         return mRuimRecords.getMdnNumber();
     }
 
+    public String getMin() {
+        return mRuimRecords.getMin();
+    }
+
     public void getCallWaiting(Message onComplete) {
         mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
     }
@@ -476,10 +499,10 @@
 
             ret = DataState.CONNECTED;
         } else if (mSST == null) {
-            // Radio Technology Change is ongoning, dispose() and removeReferences() have
-            // already been called
+             // Radio Technology Change is ongoning, dispose() and removeReferences() have
+             // already been called
 
-            ret = DataState.DISCONNECTED;
+             ret = DataState.DISCONNECTED;
         } else if (mSST.getCurrentCdmaDataConnectionState()
                 == ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
             // If we're out of service, open TCP sockets may still work
@@ -541,6 +564,21 @@
         mCM.stopDtmf(null);
     }
 
+    public void sendBurstDtmf(String dtmfString) {
+        boolean check = true;
+        for (int itr = 0;itr < dtmfString.length(); itr++) {
+            if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
+                Log.e(LOG_TAG,
+                        "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
+                check = false;
+                break;
+            }
+        }
+        if ((mCT.state ==  Phone.State.OFFHOOK)&&(check)) {
+            mCM.sendBurstDtmf(dtmfString, null);
+        }
+     }
+
     public void getAvailableNetworks(Message response) {
         Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
     }
@@ -767,6 +805,12 @@
                 }
                 break;
 
+                case EVENT_EMERGENCY_CALLBACK_MODE: {
+                    Log.d(LOG_TAG, "Event EVENT_EMERGENCY_CALLBACK_MODE Received");
+                    Intent intent =
+                        new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_ENTERED);
+                    ActivityManagerNative.broadcastStickyIntent(intent, null);
+                }
                 case EVENT_RUIM_RECORDS_LOADED:{
                     Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
                 }
@@ -800,7 +844,18 @@
                 case EVENT_NV_READY:{
                     Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
                     //Inform the Service State Tracker
+                    mEriManager.loadEriFile();
                     mNvLoadedRegistrants.notifyRegistrants();
+                    if(mEriManager.isEriFileLoaded()) {
+                        // when the ERI file is loaded
+                        Log.d(LOG_TAG, "ERI read, notify registrants");
+                        mEriFileLoadedRegistrants.notifyRegistrants();
+                    }
+                }
+                break;
+
+                case EVENT_CDMA_CALL_WAITING:{
+                    Log.d(LOG_TAG, "Event EVENT_CDMA_CALL_WAITING Received");
                 }
                 break;
 
@@ -841,6 +896,15 @@
         mNvLoadedRegistrants.remove(h);
     }
 
+    public void registerForEriFileLoaded(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mEriFileLoadedRegistrants.add(r);
+    }
+
+    public void unregisterForEriFileLoaded(Handler h) {
+        mEriFileLoadedRegistrants.remove(h);
+    }
+
      // override for allowing access from other classes of this package
      /**
       * {@inheritDoc}
@@ -866,15 +930,22 @@
      /**
       * Set the TTY mode of the CDMAPhone
       */
-     public void setTTYModeEnabled(boolean enable, Message onComplete) {
-         this.mCM.setTTYModeEnabled(enable, onComplete);
+     public void setTTYMode(int ttyMode, Message onComplete) {
+         this.mCM.setTTYMode(ttyMode, onComplete);
 }
 
      /**
       * Queries the TTY mode of the CDMAPhone
       */
-     public void queryTTYModeEnabled(Message onComplete) {
-         this.mCM.queryTTYModeEnabled(onComplete);
+     public void queryTTYMode(Message onComplete) {
+         this.mCM.queryTTYMode(onComplete);
+     }
+
+     /**
+      * Sends Exit EmergencyCallbackMode Exit request on CDMAPhone
+      */
+     public void exitEmergencyCallbackMode(Message onComplete) {
+         this.mCM.exitEmergencyCallbackMode(onComplete);
      }
 
      /**
@@ -908,4 +979,244 @@
      public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
          mSMS.setCellBroadcastConfig(configValuesArray, response);
      }
+
+     public void registerForOtaSessionStatus(Handler h, int what, Object obj){
+         mCM.registerForOtaSessionStatus(h, what, obj);
+     }
+
+     public void unregisterForOtaSessionStatus(Handler h){
+         mCM.unregisterForOtaSessionStatus(h);
+     }
+
+/**
+ * TODO(Teleca): The code in getCdmaEriIconIndex, getCdmaEriIconMode & getCdmaEriText share a
+ * lot of logic, refactor.
+ */
+    /**
+     * Returns the CDMA ERI icon index to display,
+     * it returns 1, EriInfo.ROAMING_INDICATOR_OFF, in case there is no icon to display
+     */
+    @Override
+    public int getCdmaEriIconIndex() {
+        int roamInd = getServiceState().getCdmaRoamingIndicator();
+        int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
+        int ret = -1;
+
+        switch (roamInd) {
+            // Handling the standard roaming indicator (non-ERI)
+            case EriInfo.ROAMING_INDICATOR_ON:
+            case EriInfo.ROAMING_INDICATOR_OFF:
+            case EriInfo.ROAMING_INDICATOR_FLASH:
+                Log.d(LOG_TAG, "Using Standard Roaming Indicator (non-ERI): " + roamInd);
+                ret = roamInd;
+            break;
+
+            // Handling the Enhanced Roaming Indicator (roamInd > 2)
+            default:
+                if (!mEriManager.isEriFileLoaded()) {
+                    /**
+                     * TODO(Teleca): What is going on here? Conditionals on the variable being
+                     * switched? Seems unreasonably confusing... Especially since the above comment
+                     * indicates this should always be true... If we used explicit returns, the
+                     * switch could be used to filter specific cases for early bail, and the rest
+                     * could then be dealt with outside the switch...
+                     */
+
+                    if(defRoamInd > 2) {
+                        Log.d(LOG_TAG, "ERI File not loaded, using: "
+                                + EriInfo.ROAMING_INDICATOR_FLASH);
+                        ret = EriInfo.ROAMING_INDICATOR_FLASH;
+                    } else {
+                        Log.d(LOG_TAG, "ERI File not loaded, using: " + defRoamInd);
+                        ret = defRoamInd;
+                    }
+                } else if (mEriManager.getEriInfo(roamInd) == null) {
+                    if(mEriManager.getEriInfo(defRoamInd) == null) {
+/**
+ * TODO(Teleca): Why the redundant code? Especially since it results in this very strange looking
+ * almost-identical conditional... How about calling each version of mEriManager.getEriInfo just
+ * once, and conditionalizing on the results..
+ */
+                        Log.e(LOG_TAG, "Error: ERI entry: " + roamInd
+                                + " not present, defRoamInd: " + defRoamInd
+                                + " not defined in ERI file");
+                        ret = EriInfo.ROAMING_INDICATOR_ON;
+                    } else {
+                        int iconIndex = mEriManager.getEriInfo(defRoamInd).mIconIndex;
+                        Log.d(LOG_TAG, "ERI entry " + roamInd + " not present, using icon: "
+                                + iconIndex);
+                        ret = iconIndex;
+                    }
+                } else {
+                    int iconIndex = mEriManager.getEriInfo(roamInd).mIconIndex;
+                    Log.d(LOG_TAG, "Using ERI icon: " + iconIndex);
+                    ret = iconIndex;
+                }
+            break;
+        }
+        return ret;
+    }
+
+    /**
+     * Returns the CDMA ERI icon mode,
+     * 0 - ON
+     * 1 - FLASHING
+     */
+    @Override
+    public int getCdmaEriIconMode() {
+        int roamInd = getServiceState().getCdmaRoamingIndicator();
+        int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
+        int ret = -1;
+
+        switch (roamInd) {
+            // Handling the standard roaming indicator (non-ERI)
+            case EriInfo.ROAMING_INDICATOR_ON:
+            case EriInfo.ROAMING_INDICATOR_OFF:
+                Log.d(LOG_TAG, "Using Standard Roaming Indicator (non-ERI): normal");
+                ret = EriInfo.ROAMING_ICON_MODE_NORMAL;
+            break;
+
+            case EriInfo.ROAMING_INDICATOR_FLASH:
+                Log.d(LOG_TAG, "Using Standard Roaming Indicator (non-ERI): flashing");
+                ret = EriInfo.ROAMING_ICON_MODE_FLASH;
+            break;
+
+            // Handling the Enhanced Roaming Indicator (roamInd > 2)
+            default:
+                if (!mEriManager.isEriFileLoaded()) {
+                    if(defRoamInd > 2) {
+                        Log.d(LOG_TAG, "ERI File not loaded, defRoamInd > 2, flashing");
+                        ret = EriInfo.ROAMING_ICON_MODE_FLASH;
+                    } else {
+                        switch (defRoamInd) {
+                            // Handling the standard roaming indicator (non-ERI)
+                            case EriInfo.ROAMING_INDICATOR_ON:
+                            case EriInfo.ROAMING_INDICATOR_OFF:
+                                Log.d(LOG_TAG, "ERI File not loaded, normal");
+                                ret = EriInfo.ROAMING_ICON_MODE_NORMAL;
+                            break;
+
+                            case EriInfo.ROAMING_INDICATOR_FLASH:
+                                Log.d(LOG_TAG, "ERI File not loaded, normal");
+                                ret = EriInfo.ROAMING_ICON_MODE_FLASH;
+                            break;
+                        }
+                    }
+                } else if (mEriManager.getEriInfo(roamInd) == null) {
+                    if(mEriManager.getEriInfo(defRoamInd) == null) {
+                        Log.e(LOG_TAG, "Error: defRoamInd not defined in ERI file, normal");
+                        ret =  EriInfo.ROAMING_ICON_MODE_NORMAL;
+                    } else {
+                        int mode = mEriManager.getEriInfo(defRoamInd).mIconMode;
+                        Log.d(LOG_TAG, "ERI entry " + roamInd + " not present, icon  mode: "
+                                + mode);
+                        ret = mode;
+                    }
+                } else {
+                    int mode = mEriManager.getEriInfo(roamInd).mIconMode;
+                    Log.d(LOG_TAG, "Using ERI icon mode: " + mode);
+                    ret = mode;
+                }
+            break;
+        }
+        return ret;
+    }
+
+    /**
+     * Returns the CDMA ERI text,
+     */
+    @Override
+    public String getCdmaEriText() {
+        int roamInd = getServiceState().getCdmaRoamingIndicator();
+        int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
+        String ret = "ERI text";
+
+        switch (roamInd) {
+            // Handling the standard roaming indicator (non-ERI)
+            case EriInfo.ROAMING_INDICATOR_ON:
+                ret = EriInfo.ROAMING_TEXT_0;
+            break;
+            case EriInfo.ROAMING_INDICATOR_OFF:
+                ret = EriInfo.ROAMING_TEXT_1;
+            break;
+            case EriInfo.ROAMING_INDICATOR_FLASH:
+                ret = EriInfo.ROAMING_TEXT_2;
+            break;
+
+            // Handling the standard ERI
+            case 3:
+                ret = EriInfo.ROAMING_TEXT_3;
+            break;
+            case 4:
+                ret = EriInfo.ROAMING_TEXT_4;
+            break;
+            case 5:
+                ret = EriInfo.ROAMING_TEXT_5;
+            break;
+            case 6:
+                ret = EriInfo.ROAMING_TEXT_6;
+            break;
+            case 7:
+                ret = EriInfo.ROAMING_TEXT_7;
+            break;
+            case 8:
+                ret = EriInfo.ROAMING_TEXT_8;
+            break;
+            case 9:
+                ret = EriInfo.ROAMING_TEXT_9;
+            break;
+            case 10:
+                ret = EriInfo.ROAMING_TEXT_10;
+            break;
+            case 11:
+                ret = EriInfo.ROAMING_TEXT_11;
+            break;
+            case 12:
+                ret = EriInfo.ROAMING_TEXT_12;
+            break;
+
+            // Handling the non standard Enhanced Roaming Indicator (roamInd > 63)
+            default:
+                if (!mEriManager.isEriFileLoaded()) {
+                    if(defRoamInd > 2) {
+                        Log.d(LOG_TAG, "ERI File not loaded, defRoamInd > 2, " +
+                                EriInfo.ROAMING_TEXT_2);
+                        ret = EriInfo.ROAMING_TEXT_2;
+                    } else {
+                        switch (defRoamInd) {
+                            // Handling the standard roaming indicator (non-ERI)
+                            case EriInfo.ROAMING_INDICATOR_ON:
+                                Log.d(LOG_TAG, "ERI File not loaded, " + EriInfo.ROAMING_TEXT_0);
+                                ret = EriInfo.ROAMING_TEXT_0;
+                            break;
+                            case EriInfo.ROAMING_INDICATOR_OFF:
+                                Log.d(LOG_TAG, "ERI File not loaded, " + EriInfo.ROAMING_TEXT_1);
+                                ret = EriInfo.ROAMING_TEXT_1;
+                            break;
+                            case EriInfo.ROAMING_INDICATOR_FLASH:
+                                Log.d(LOG_TAG, "ERI File not loaded, " + EriInfo.ROAMING_TEXT_2);
+                                ret = EriInfo.ROAMING_TEXT_2;
+                            break;
+                        }
+                    }
+                } else if (mEriManager.getEriInfo(roamInd) == null) {
+                    if(mEriManager.getEriInfo(defRoamInd) == null) {
+                        Log.e(LOG_TAG, "Error: defRoamInd not defined in ERI file, "
+                                + EriInfo.ROAMING_TEXT_0);
+                        ret = EriInfo.ROAMING_TEXT_0;
+                    } else {
+                        String eriText = mEriManager.getEriInfo(defRoamInd).mEriText;
+                        Log.d(LOG_TAG, "ERI entry " + roamInd + " not present, eri text: "
+                                + eriText);
+                        ret = eriText;
+                    }
+                } else {
+                    String eriText = mEriManager.getEriInfo(roamInd).mEriText;
+                    Log.d(LOG_TAG, "Using ERI text: " + eriText);
+                    ret = eriText;
+                }
+            break;
+        }
+        return ret;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
index ea557b2..9af245c 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
@@ -25,26 +25,40 @@
  *
  */
 public interface CallFailCause {
-    static final int NORMAL_CLEARING     = 16;
+    static final int NORMAL_CLEARING                = 16;
     // Busy Tone
-    static final int USER_BUSY           = 17;
+    static final int USER_BUSY                      = 17;
 
+    // TODO(Teleca): Should we remove commented out values?
 //    // No Tone
-//    static final int NUMBER_CHANGED      = 22;
-//    static final int STATUS_ENQUIRY      = 30;
-    static final int NORMAL_UNSPECIFIED  = 31;
+//    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;
+    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 ACM_LIMIT_EXCEEDED             = 68;
+    static final int CALL_BARRED                    = 240;
+    static final int FDN_BLOCKED                    = 241;
+
+    static final int CDMA_LOCKED_UNTIL_POWER_CYCLE  = 1000;
+    static final int CDMA_DROP                      = 1001;
+    static final int CDMA_INTERCEPT                 = 1002;
+    static final int CDMA_REORDER                   = 1003;
+    static final int CDMA_SO_REJECT                 = 1004;
+    static final int CDMA_RETRY_ORDER               = 1005;
+    static final int CDMA_ACCESS_FAILURE            = 1006;
+    static final int CDMA_PREEMPTED                 = 1007;
+
+    // For non-emergency number dialed while in emergency callback mode.
+    static final int CDMA_NOT_EMERGENCY             = 1008;
+
     static final int ERROR_UNSPECIFIED = 0xffff;
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java
new file mode 100644
index 0000000..64841d7
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallWaiting.java
@@ -0,0 +1,33 @@
+/*
+ * 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 com.android.internal.telephony.CdmaInformationRecord;
+
+public class CdmaCallWaiting {
+    public String number;
+    public int numberPresentation;
+    public String name;
+
+    public CdmaInformationRecord.CdmaSignalInfoRec signalInfoRecord =
+                                   new CdmaInformationRecord.CdmaSignalInfoRec();
+
+    @Override
+    public String toString() {
+        return "CdmaCallWaiting: {" + " number: " + number + " numberPresentation: "
+                + numberPresentation + " name: " + name + " signalInfoRecord: "
+                + signalInfoRecord + " }";
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index cdad4a7..0a237c6 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -84,7 +84,7 @@
     static final int EVENT_PAUSE_DONE = 2;
     static final int EVENT_NEXT_POST_DIAL = 3;
     static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
-    
+
     //***** Constants
     static final int PAUSE_DELAY_FIRST_MILLIS = 100;
     static final int PAUSE_DELAY_MILLIS = 3 * 1000;
@@ -139,7 +139,7 @@
     CdmaConnection (Context context, String dialString, CdmaCallTracker ct, CdmaCall parent) {
         createWakeLock(context);
         acquireWakeLock();
-		
+
         owner = ct;
         h = new MyHandler(owner.getLooper());
 
@@ -344,6 +344,32 @@
         switch (causeCode) {
             case CallFailCause.USER_BUSY:
                 return DisconnectCause.BUSY;
+            case CallFailCause.NO_CIRCUIT_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.CDMA_LOCKED_UNTIL_POWER_CYCLE:
+                return DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE;
+            case CallFailCause.CDMA_DROP:
+                return DisconnectCause.CDMA_DROP;
+            case CallFailCause.CDMA_INTERCEPT:
+                return DisconnectCause.CDMA_INTERCEPT;
+            case CallFailCause.CDMA_REORDER:
+                return DisconnectCause.CDMA_REORDER;
+            case CallFailCause.CDMA_SO_REJECT:
+                return DisconnectCause.CDMA_SO_REJECT;
+            case CallFailCause.CDMA_RETRY_ORDER:
+                return DisconnectCause.CDMA_RETRY_ORDER;
+            case CallFailCause.CDMA_ACCESS_FAILURE:
+                return DisconnectCause.CDMA_ACCESS_FAILURE;
+            case CallFailCause.CDMA_PREEMPTED:
+                return DisconnectCause.CDMA_PREEMPTED;
+            case CallFailCause.CDMA_NOT_EMERGENCY:
+                return DisconnectCause.CDMA_NOT_EMERGENCY;
             case CallFailCause.ERROR_UNSPECIFIED:
             case CallFailCause.NORMAL_CLEARING:
             default:
@@ -352,7 +378,7 @@
                 if (serviceState == ServiceState.STATE_POWER_OFF) {
                     return DisconnectCause.POWER_OFF;
                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
-                        || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
+                        || serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
                     return DisconnectCause.OUT_OF_SERVICE;
                 } else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
                         && phone.getIccCard().getState() != RuimCard.State.READY) {
@@ -549,7 +575,7 @@
 
         return postDialString.substring(nextPostDialChar);
     }
-    
+
     @Override
     protected void finalize()
     {
@@ -583,7 +609,7 @@
             c = 0;
         } else {
             boolean isValid;
-            
+
             setPostDialState(PostDialState.STARTED);
 
             c = postDialString.charAt(nextPostDialChar++);
@@ -653,31 +679,31 @@
     }
 
     /**
-     * Set post dial state and acquire wake lock while switching to "started" 
-     * state, the wake lock will be released if state switches out of "started" 
-     * state or after WAKE_LOCK_TIMEOUT_MILLIS. 
+     * Set post dial state and acquire wake lock while switching to "started"
+     * state, the wake lock will be released if state switches out of "started"
+     * state or after WAKE_LOCK_TIMEOUT_MILLIS.
      * @param s new PostDialState
      */
     private void setPostDialState(PostDialState s) {
-        if (postDialState != PostDialState.STARTED 
+        if (postDialState != PostDialState.STARTED
                 && s == PostDialState.STARTED) {
             acquireWakeLock();
             Message msg = h.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
             h.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
-        } else if (postDialState == PostDialState.STARTED 
+        } else if (postDialState == PostDialState.STARTED
                 && s != PostDialState.STARTED) {
             h.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
             releaseWakeLock();
         }
         postDialState = s;
     }
-    
+
     private void
     createWakeLock(Context context) {
         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
     }
-    
+
     private void
     acquireWakeLock() {
         log("acquireWakeLock");
@@ -693,7 +719,7 @@
             }
         }
     }
-    
+
     private void log(String msg) {
         Log.d(LOG_TAG, "[CDMAConn] " + msg);
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 651c5051..64f9387 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -44,6 +44,7 @@
 import android.util.Log;
 
 import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataCallState;
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.DataConnection.FailCause;
 import com.android.internal.telephony.DataConnectionTracker;
@@ -98,6 +99,13 @@
             "com.android.internal.telephony.cdma-reconnect";
     private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
 
+    /**
+     * Constants for the data connection activity:
+     * physical link down/up
+     */
+     private static final int DATA_CONNECTION_ACTIVE_PH_LINK_DOWN = 1;
+     private static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2;
+
     // 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.
@@ -258,7 +266,7 @@
     }
 
     /**
-     * Simply tear down data connections due to radio off 
+     * Simply tear down data connections due to radio off
      * and don't setup again.
      */
     public void cleanConnectionBeforeRadioOff() {
@@ -515,7 +523,7 @@
          * override it with an unconditional power on.
          */
     }
-    
+
     private Runnable mPollNetStat = new Runnable() {
 
         public void run() {
@@ -608,19 +616,19 @@
     /**
      * 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 
+     * @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) ) { 
+             Phone.REASON_DATA_DISABLED.equals(reason) ) {
             retry = false;
         }
         return retry;
-    }   
+    }
 
     private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
         if (state == State.FAILED) {
@@ -843,6 +851,8 @@
     }
 
     protected void onDataStateChanged (AsyncResult ar) {
+        ArrayList<DataCallState> dataCallStates = (ArrayList<DataCallState>)(ar.result);
+
         if (ar.exception != null) {
             // This is probably "radio not available" or something
             // of that sort. If so, the whole connection is going
@@ -851,7 +861,14 @@
         }
 
         if (state == State.CONNECTED) {
-            Log.i(LOG_TAG, "Data connection has changed.");
+            if (dataCallStates.get(0).active == DATA_CONNECTION_ACTIVE_PH_LINK_UP ) {
+                activity = Activity.NONE;
+                phone.notifyDataActivity();
+            } else if (dataCallStates.get(0).active == DATA_CONNECTION_ACTIVE_PH_LINK_DOWN ) {
+                activity = Activity.DORMANT;
+                phone.notifyDataActivity();
+            }
+        } else {
 
             int cid = -1;
             EventLog.List val = new EventLog.List(cid,
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index d5cad1c..dbb0f93 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -33,6 +33,7 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Telephony.Intents;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.cdma.CdmaCellLocation;
 import android.text.TextUtils;
 import android.util.EventLog;
@@ -70,8 +71,13 @@
     CdmaCellLocation cellLoc;
     CdmaCellLocation newCellLoc;
 
-    int rssi = 99;  // signal strength 0-31, 99=unknown
-    // That's "received signal strength indication" fyi
+    /**
+     * TODO(Teleca): I don't think the initialization to -1 for all of these are
+     * really necessary, I don't seem them in GsmServiceStateTracker. Also,
+     * all of the other initialization is unnecessary as I believe Java guarantees
+     * 0, false & null, but if you think it's better than do all of them there are
+     * a few that aren't initialized.
+     */
 
     /**
      *  The access technology currently in use: DATA_ACCESS_
@@ -80,9 +86,16 @@
     private int newNetworkType = 0;
 
     private boolean mCdmaRoaming = false;
+    private int mRoamingIndicator = -1;
+    private int mIsInPrl = -1;
+    private int mDefaultRoamingIndicator = -1;
 
-    private int cdmaDataConnectionState = -1;//Initial we assume no data connection
-    private int newCdmaDataConnectionState = -1;//Initial we assume no data connection
+    /**
+     * TODO(Teleca): Maybe these should be initialized to STATE_OUT_OF_SERVICE like gprsState
+     * in GsmServiceStateTracker and remove the comment.
+     */
+    private int cdmaDataConnectionState = -1; // Initially we assume no data connection
+    private int newCdmaDataConnectionState = -1; // Initially we assume no data connection
     private int mRegistrationState = -1;
     private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList();
     private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
@@ -95,12 +108,25 @@
 
     // Keep track of SPN display rules, so we only broadcast intent if something changes.
     private String curSpn = null;
-    private String curPlmn = null;
+    private String curEriText = null;
     private int curSpnRule = 0;
 
+    private String mMdn = null;
+    private int mHomeSystemId = -1;
+    private int mHomeNetworkId = -1;
+    private String mMin = null;
+    private boolean isEriTextLoaded = false;
+    private boolean isSubscriptionFromRuim = false;
+
+    /**
+     * TODO(Teleca): Is this purely for debugging purposes, or do we expect this string to be
+     * passed around (eg, to the UI)? If the latter, it would be better to pass around a
+     * reasonCode, and let the UI provide its own strings.
+     */
+    private String mRegistrationDeniedReason = null;
+
     //***** Constants
     static final String LOG_TAG = "CDMA";
-    static final String TMUK = "23430";
 
     private ContentResolver cr;
 
@@ -124,6 +150,7 @@
         newSS = new ServiceState();
         cellLoc = new CdmaCellLocation();
         newCellLoc = new CdmaCellLocation();
+        mSignalStrength = new SignalStrength();
 
         cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
@@ -133,7 +160,8 @@
 
         cm.registerForRUIMReady(this, EVENT_RUIM_READY, null);
 
-        phone.registerForNvLoaded(this, EVENT_NV_LOADED,null);
+        cm.registerForNVReady(this, EVENT_NV_READY, null);
+        phone.registerForEriFileLoaded(this, EVENT_ERI_FILE_LOADED, null);
 
         // system setting property AIRPLANE_MODE_ON is set in Settings.
         int airplaneMode = Settings.System.getInt(
@@ -145,7 +173,7 @@
         cr.registerContentObserver(
                 Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
                 mAutoTimeObserver);
-        setRssiDefaultValues();
+        setSignalStrengthDefaultValues();
 
         mNeedToRegForRuimLoaded = true;
     }
@@ -156,14 +184,15 @@
         cm.unregisterForRadioStateChanged(this);
         cm.unregisterForNetworkStateChanged(this);
         cm.unregisterForRUIMReady(this);
-        phone.unregisterForNvLoaded(this);
+        cm.unregisterForNVReady(this);
+        phone.unregisterForEriFileLoaded(this);
         phone.mRuimRecords.unregisterForRecordsLoaded(this);
         cm.unSetOnSignalStrengthUpdate(this);
         cr.unregisterContentObserver(this.mAutoTimeObserver);
     }
 
     protected void finalize() {
-        if(DBG) Log.d(LOG_TAG, "CdmaServiceStateTracker finalized");
+        if (DBG) log("CdmaServiceStateTracker finalized");
     }
 
     void registerForNetworkAttach(Handler h, int what, Object obj) {
@@ -246,13 +275,21 @@
             // The RUIM is now ready i.e if it was locked
             // it has been unlocked. At this stage, the radio is already
             // powered on.
+            isSubscriptionFromRuim = true;
             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_NV_READY:
+            isSubscriptionFromRuim = false;
             pollState();
             // Signal strength polling stops when radio is off
             queueNextSignalStrengthPoll();
@@ -328,9 +365,9 @@
             }
             break;
 
-        case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA: //Fall through
-        case EVENT_POLL_STATE_REGISTRATION_CDMA: //Fall through
+        case EVENT_POLL_STATE_REGISTRATION_CDMA:
         case EVENT_POLL_STATE_OPERATOR_CDMA:
+        case EVENT_POLL_STATE_CDMA_SUBSCRIPTION:
             ar = (AsyncResult) msg.obj;
             handlePollStateResult(msg.what, ar);
             break;
@@ -355,7 +392,6 @@
             break;
 
         case EVENT_RUIM_RECORDS_LOADED:
-        case EVENT_NV_LOADED:
             updateSpnDisplay();
             break;
 
@@ -367,6 +403,12 @@
             }
             break;
 
+        case EVENT_ERI_FILE_LOADED:
+            // Repoll the state once the ERI file has been loaded
+            if (DBG) log("[CdmaServiceStateTracker] ERI file has been loaded, repolling.");
+            pollState();
+            break;
+
         default:
             Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
         break;
@@ -391,13 +433,14 @@
                 EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
             }
             dcTracker.cleanConnectionBeforeRadioOff();
-            
-            // poll data state up to 15 times, with a 100ms delay
+
+            // 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.");
+                DataConnectionTracker.State currentState = dcTracker.getState();
+                if (currentState != DataConnectionTracker.State.CONNECTED
+                        && currentState != DataConnectionTracker.State.DISCONNECTING) {
+                    if (DBG) log("Data shutdown complete.");
                     break;
                 }
                 SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
@@ -409,29 +452,29 @@
 
     protected void updateSpnDisplay() {
 
-        // TODO Check this method again, because it is not sure at the moment how
-        // the RUIM handles the SIM stuff
+        // TODO(Teleca): Check this method again, because it is not sure at the moment how
+        // the RUIM handles the SIM stuff. Please complete this function.
 
         //int rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric());
         String spn = null; //phone.mRuimRecords.getServiceProviderName();
-        String plmn = ss.getOperatorAlphaLong();
+        String eri = ss.getOperatorAlphaLong();
 
-        if (!TextUtils.equals(this.curPlmn, plmn)) {
+        if (!TextUtils.equals(this.curEriText, eri)) {
             //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;
+            boolean showEri = 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);
+            intent.putExtra(Intents.EXTRA_SHOW_PLMN, showEri);
+            intent.putExtra(Intents.EXTRA_PLMN, eri);
             phone.getContext().sendStickyBroadcast(intent);
         }
 
         //curSpnRule = rule;
         //curSpn = spn;
-        this.curPlmn = plmn;
+        this.curEriText = eri;
     }
 
     /**
@@ -473,11 +516,17 @@
             }
         } else try {
             switch (what) {
-            case EVENT_POLL_STATE_REGISTRATION_CDMA:
-                //offset, because we don't want the first 3 values in the int-array
+            case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE,
+                                                     // the offset is because we don't want the
+                                                     // first 3 values in the
+                                                     // responseValuesRegistrationState array.
                 final int offset = 3;
                 states = (String[])ar.result;
 
+                /**
+                 * TODO(Teleca): Change from array to a "Class" or local
+                 * variables so names instead of index's can be used.
+                 */
                 int responseValuesRegistrationState[] = {
                         -1, //[0] radioTechnology
                         -1, //[1] baseStationId
@@ -486,38 +535,40 @@
                          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
+                        -1, //[7] Roaming indicator
+                        -1, //[8] Indicates if current system is in PRL
+                        -1, //[9] Is default roaming indicator from PRL
+                        -1, //[10] If registration state is 3 this is reason for denial
                 };
 
-                if (states.length > 0) {
+                if (states.length == 14) {
                     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);
                     }
+                    try {
+                        responseValuesRegistrationState[0] = Integer.parseInt(states[3]);
+                        responseValuesRegistrationState[1] = Integer.parseInt(states[4], 16);
+                        responseValuesRegistrationState[2] = Integer.parseInt(states[5], 16);
+                        responseValuesRegistrationState[3] = Integer.parseInt(states[6], 16);
+                        responseValuesRegistrationState[4] = Integer.parseInt(states[7]);
+                        responseValuesRegistrationState[5] = Integer.parseInt(states[8]);
+                        responseValuesRegistrationState[6] = Integer.parseInt(states[9]);
+                        responseValuesRegistrationState[7] = Integer.parseInt(states[10]);
+                        responseValuesRegistrationState[8] = Integer.parseInt(states[11]);
+                        responseValuesRegistrationState[9] = Integer.parseInt(states[12]);
+                        responseValuesRegistrationState[10] = Integer.parseInt(states[13]);
+                    }
+                    catch(NumberFormatException ex) {
+                        Log.w(LOG_TAG, "Warning! There is an unexpected value"
+                            + "returned as response from "
+                            + "RIL_REQUEST_REGISTRATION_STATE.");
+                    }
+                } else {
+                    throw new RuntimeException("Warning! Wrong number of parameters returned from "
+                                         + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
+                                         + states.length);
                 }
 
                 mCdmaRoaming = regCodeIsRoaming(this.mRegistrationState);
@@ -529,26 +580,62 @@
                 newSS.setSystemAndNetworkId(responseValuesRegistrationState[5],
                     responseValuesRegistrationState[6]);
 
+                mRoamingIndicator = responseValuesRegistrationState[7];
+                mIsInPrl = responseValuesRegistrationState[8];
+                mDefaultRoamingIndicator = responseValuesRegistrationState[9];
+
                 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 (responseValuesRegistrationState[10] == 0) {
+                    mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
+                } else if (responseValuesRegistrationState[10] == 1) {
+                    mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
+                } else {
+                    mRegistrationDeniedReason = "";
+                }
 
-                if (opNames != null && opNames.length >= 3) {
-                    newSS.setOperatorName (opNames[0], opNames[1], opNames[2]);
+                if (mRegistrationState == 3) {
+                    if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
                 }
                 break;
 
-            case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA:
-                ints = (int[])ar.result;
-                newSS.setIsManualSelection(ints[0] == 1);
+            case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
+                String opNames[] = (String[])ar.result;
+
+                if (opNames != null && opNames.length >= 3) {
+                    // TODO(Teleca): Is this necessary here and in the else clause?
+                    newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
+                    if (phone.mCM.getRadioState().isNVReady()) {
+                        // In CDMA in case on NV the ss.mOperatorAlphaLong is set later with the
+                        // ERI text, so here is ignored what is coming from the modem
+                        newSS.setOperatorName(null, opNames[1], opNames[2]);
+                    } else {
+                        newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
+                    }
+                } else {
+                    Log.w(LOG_TAG, "error parsing opNames");
+                }
                 break;
+
+            case EVENT_POLL_STATE_CDMA_SUBSCRIPTION: // Handle RIL_CDMA_SUBSCRIPTION
+                String cdmaSubscription[] = (String[])ar.result;
+
+                if (cdmaSubscription != null && cdmaSubscription.length >= 4) {
+                    mMdn = cdmaSubscription[0];
+                    mHomeSystemId = Integer.parseInt(cdmaSubscription[1], 16);
+                    mHomeNetworkId = Integer.parseInt(cdmaSubscription[2], 16);
+                    mMin = cdmaSubscription[3];
+
+                } else {
+                    Log.w(LOG_TAG, "error parsing cdmaSubscription");
+                }
+                break;
+
             default:
                 Log.e(LOG_TAG, "RIL response handle in wrong phone!"
                     + " Expected CDMA RIL request and get GSM RIL request.");
@@ -563,29 +650,58 @@
         pollingContext[0]--;
 
         if (pollingContext[0] == 0) {
-            newSS.setRoaming(isRoamingBetweenOperators(mCdmaRoaming, newSS));
+            boolean namMatch = false;
+            if ((mHomeSystemId != 0) && (mHomeSystemId == newSS.getSystemId()) ) {
+                namMatch = true;
+            }
 
-            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.");
+            // Setting SS Roaming (general)
+            if (isSubscriptionFromRuim) {
+                newSS.setRoaming(isRoamingBetweenOperators(mCdmaRoaming, newSS));
+            } else {
+                newSS.setRoaming(mCdmaRoaming);
+            }
+
+            /**
+             * TODO(Teleca): This would be simpler if mIsInPrl was a "boolean" as the
+             * name implies rather than tri-state. Above I've suggested that the -1's
+             * might be able to be removed, if so please simplify this. Otherwise change
+             * the name to mPrlState or some such. Also the logic can be simplified
+             * by testing for "mIsInPrl" only once.
+             */
+            // Setting SS CdmaRoamingIndicator and CdmaDefaultRoamingIndicator
+            // TODO(Teleca): use constants for the standard roaming indicators
+            if (mIsInPrl == 0 && mRegistrationState == 5) {
+                // System is acquired but prl not loaded or no prl match
+                newSS.setCdmaRoamingIndicator(2); //FLASHING
+            } else if (!namMatch && (mIsInPrl == 1)) {
+                // System is acquired, no nam match, prl match
+                newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+            } else if (namMatch && (mIsInPrl == 1) && mRoamingIndicator <= 2) {
+                // System is acquired, nam match, prl match, mRoamingIndicator <= 2
+                newSS.setCdmaRoamingIndicator(1); //OFF
+            } else if (namMatch && (mIsInPrl == 1) && mRoamingIndicator > 2) {
+                // System is acquired, nam match, prl match, mRoamingIndicator > 2
+                newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+            }
+            newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
+
+            // NOTE: Some operator may require to override the mCdmaRoaming (set by the modem)
+            // depending on the mRoamingIndicator.
+
+            if (DBG) {
+                log("Set CDMA Roaming Indicator to: " + newSS.getCdmaRoamingIndicator()
+                    + ". mCdmaRoaming = " + mCdmaRoaming + ",  namMatch = " + namMatch
+                    + ", mIsInPrl= " + mIsInPrl + ", mRoamingIndicator = " + mRoamingIndicator
+                    + ", mDefaultRoamingIndicator= " + mDefaultRoamingIndicator);
             }
             pollStateDone();
         }
 
     }
 
-    private void setRssiDefaultValues() {
-        rssi = 99;
+    private void setSignalStrengthDefaultValues() {
+        mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, false);
     }
 
     /**
@@ -606,7 +722,7 @@
         case RADIO_UNAVAILABLE:
             newSS.setStateOutOfService();
             newCellLoc.setStateInvalid();
-            setRssiDefaultValues();
+            setSignalStrengthDefaultValues();
             mGotCountryCode = false;
 
             pollStateDone();
@@ -615,7 +731,7 @@
         case RADIO_OFF:
             newSS.setStateOff();
             newCellLoc.setStateInvalid();
-            setRssiDefaultValues();
+            setSignalStrengthDefaultValues();
             mGotCountryCode = false;
 
             pollStateDone();
@@ -627,10 +743,10 @@
             log("Radio Technology Change ongoing, setting SS to off");
             newSS.setStateOff();
             newCellLoc.setStateInvalid();
-            setRssiDefaultValues();
+            setSignalStrengthDefaultValues();
             mGotCountryCode = false;
 
-            pollStateDone();
+            //NOTE: pollStateDone() is not needed in this case
             break;
 
         default:
@@ -639,20 +755,21 @@
             // 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));
+            // RIL_REQUEST_CDMA_SUBSCRIPTION is necessary for CDMA
+            cm.getCDMASubscription(
+                    obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION, pollingContext));
 
-        pollingContext[0]++;
-        //RIL_REQUEST_REGISTRATION_STATE is necessary for CDMA
-        cm.getRegistrationState(
-                obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, pollingContext));
+            pollingContext[0]++;
+            // RIL_REQUEST_OPERATOR is necessary for CDMA
+            cm.getOperator(
+                    obtainMessage(EVENT_POLL_STATE_OPERATOR_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;
+            pollingContext[0]++;
+            // RIL_REQUEST_REGISTRATION_STATE is necessary for CDMA
+            cm.getRegistrationState(
+                    obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, pollingContext));
+
+            break;
         }
     }
 
@@ -685,12 +802,7 @@
 
     private void
     pollStateDone() {
-        if (DBG) {
-            Log.d(LOG_TAG, "Poll ServiceState done: " +
-                    " oldSS=[" + ss );
-            Log.d(LOG_TAG, "Poll ServiceState done: " +
-                    " newSS=[" + newSS);
-        }
+        if (DBG) log("Poll ServiceState done: oldSS=[" + ss + "] newSS=[" + newSS + "]");
 
         boolean hasRegistered =
             ss.getState() != ServiceState.STATE_IN_SERVICE
@@ -757,6 +869,22 @@
         }
 
         if (hasChanged) {
+            if (phone.mCM.getRadioState().isNVReady()) {
+                String eriText;
+                // Now the CDMAPhone sees the new ServiceState so it can get the new ERI text
+                if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+                    eriText = phone.getCdmaEriText();
+                } else {
+                    // Note that this is valid only for mRegistrationState 2,3,4, not 0!
+                    /**
+                     * TODO(Teleca): From the comment this apparently isn't always true
+                     * should there be additional logic with other strings?
+                     */
+                    eriText = EriInfo.SEARCHING_TEXT;
+                }
+                ss.setCdmaEriText(eriText);
+            }
+
             String operatorNumeric;
 
             phone.setSystemProperty(PROPERTY_OPERATOR_ALPHA,
@@ -784,8 +912,6 @@
 
             phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
                     ss.getRoaming() ? "true" : "false");
-            phone.setSystemProperty(PROPERTY_OPERATOR_ISMANUAL,
-                    ss.getIsManualSelection() ? "true" : "false");
 
             updateSpnDisplay();
             phone.notifyServiceStateChanged(ss);
@@ -825,10 +951,7 @@
             // 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()));
-        }
+        if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID()));
         return guess;
     }
 
@@ -865,41 +988,49 @@
         msg = obtainMessage();
         msg.what = EVENT_POLL_SIGNAL_STRENGTH;
 
-        // TODO Done't poll signal strength if screen is off
+        // TODO(Teleca): Don't poll signal strength if screen is off
         sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
     }
 
     /**
-     *  send signal-strength-changed notification if rssi changed
+     *  send signal-strength-changed notification if changed
      *  Called both for solicited and unsolicited signal stength updates
      */
     private void
     onSignalStrengthResult(AsyncResult ar) {
-        int oldRSSI = rssi;
+        SignalStrength oldSignalStrength = mSignalStrength;
 
         if (ar.exception != null) {
-            // 99 = unknown
-            // most likely radio is resetting/disconnected
-            rssi = 99;
+            // Most likely radio is resetting/disconnected change to default values.
+            setSignalStrengthDefaultValues();
         } else {
             int[] ints = (int[])ar.result;
+            int offset = 2;
 
-            // 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;
+            int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -1;
+            int cdmaEcio = (ints[offset+1] > 0) ? -ints[offset+1] : -1;
+
+            int evdoRssi = -1;
+            int evdoEcio = -1;
+            int evdoSnr = -1;
+            if ((networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
+                    || (networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
+                evdoRssi = (ints[offset+2] > 0) ? -ints[offset+2] : -1;
+                evdoEcio = (ints[offset+3] > 0) ? -ints[offset+3] : -1;
+                evdoSnr  = ((ints[offset+4] > 0) && (ints[offset+4] <= 8)) ? ints[offset+4] : -1;
             }
+
+            mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio,
+                    evdoRssi, evdoEcio, evdoSnr, false);
         }
 
-        if (rssi != oldRSSI) {
+        if (!mSignalStrength.equals(oldSignalStrength)) {
             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");
+                log("onSignalStrengthResult() Phone already destroyed: " + ex
+                        + "SignalStrength not notified");
            }
         }
     }
@@ -943,9 +1074,7 @@
         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)
+        case 5:// 5 is "Registered, roaming"
             return ServiceState.STATE_IN_SERVICE;
 
         default:
@@ -983,6 +1112,8 @@
     boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) {
         String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
 
+        // NOTE: in case of RUIM we should completely ignore the ERI data file and
+        // mOperatorAlphaLong is set from RIL_REQUEST_OPERATOR response 0 (alpha ONS)
         String onsl = s.getOperatorAlphaLong();
         String onss = s.getOperatorAlphaShort();
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriInfo.java b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
new file mode 100644
index 0000000..40358c8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/EriInfo.java
@@ -0,0 +1,65 @@
+/*
+ * 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 final class EriInfo {
+
+    public static final int ROAMING_INDICATOR_ON    = 0;
+    public static final int ROAMING_INDICATOR_OFF   = 1;
+    public static final int ROAMING_INDICATOR_FLASH = 2;
+
+    public static final int ROAMING_ICON_MODE_NORMAL    = 0;
+    public static final int ROAMING_ICON_MODE_FLASH     = 1;
+
+    /**
+     * TODO(Teleca): These strings appear to be used by the UI
+     * hence they must be changed to resources so they can be
+     * translated to the appropriate language.
+     */
+    public static final String ROAMING_TEXT_0  = "Roaming Indicator On";
+    public static final String ROAMING_TEXT_1  = "Roaming Indicator Off";
+    public static final String ROAMING_TEXT_2  = "Roaming Indicator Flashing";
+    public static final String ROAMING_TEXT_3  = "Out of Neighborhood";
+    public static final String ROAMING_TEXT_4  = "Out of Building";
+    public static final String ROAMING_TEXT_5  = "Roaming - Preferred System";
+    public static final String ROAMING_TEXT_6  = "Roaming - Available System";
+    public static final String ROAMING_TEXT_7  = "Roaming - Alliance Partner";
+    public static final String ROAMING_TEXT_8  = "Roaming - Premium Partner";
+    public static final String ROAMING_TEXT_9  = "Roaming - Full Service Functionality";
+    public static final String ROAMING_TEXT_10 = "Roaming - Partial Service Functionality";
+    public static final String ROAMING_TEXT_11 = "Roaming Banner On";
+    public static final String ROAMING_TEXT_12 = "Roaming Banner Off";
+
+    public static final String SEARCHING_TEXT  = "Searching for Svc.";
+
+
+    public int mRoamingIndicator;
+    public int mIconIndex;
+    public int mIconMode;
+    public String mEriText;
+    public int mCallPromptId;
+    public int mAlertId;
+
+    public EriInfo (int roamingIndicator, int iconIndex, int iconMode, String eriText,
+            int callPromptId, int alertId) {
+
+        this.mRoamingIndicator = roamingIndicator;
+        this.mIconIndex = iconIndex;
+        this.mIconMode = iconMode;
+        this.mEriText = eriText;
+        this.mCallPromptId = callPromptId;
+        this.mAlertId = alertId;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/EriManager.java b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
new file mode 100644
index 0000000..d905e66
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/EriManager.java
@@ -0,0 +1,224 @@
+/*
+ * 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.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+
+import com.android.internal.util.XmlUtils;
+
+import java.util.HashMap;
+
+/**
+ * TODO(Teleca): Please as some comments on how this class is to
+ * be used. We've removed Handler as a base class and instead
+ * recommend that child classes add a Handler as a member if its
+ * needed.
+ */
+
+
+public final class EriManager {
+
+    class EriFile {
+        public static final int MAX_ERI_ENTRIES = 30;
+
+        public int mVersionNumber;                      // File version number
+        public int mNumberOfEriEntries;                 // Number of entries
+        public int mEriFileType;                        // Eri Phase 0/1
+        //public int mNumberOfIconImages;               // reserved for future use
+        //public int mIconImageType;                    // reserved for future use
+        public String[] mCallPromptId;                  // reserved for future use
+        public HashMap<Integer, EriInfo> mRoamIndTable; // Roaming Indicator Table
+
+        public EriFile() {
+            this.mVersionNumber = -1;
+            this.mNumberOfEriEntries = 0;
+            this.mEriFileType = -1;
+            this.mCallPromptId = new String[] { "", "", "" };
+            this.mRoamIndTable = new HashMap<Integer, EriInfo>();
+        }
+
+    }
+
+    static final String LOG_TAG = "CDMA";
+
+    public static final int ERI_FROM_XML          = 0;
+    public static final int ERI_FROM_FILE_SYSTEM  = 1;
+    public static final int ERI_FROM_MODEM        = 2;
+
+    private PhoneBase mPhone;
+    private Context mContext;
+    private int mEriFileSource = ERI_FROM_XML;
+    private boolean isEriFileLoaded = false;
+    private EriFile mEriFile;
+
+    public EriManager(PhoneBase phone, Context context, int eriFileSource) {
+        this.mPhone = phone;
+        this.mContext = context;
+        this.mEriFileSource = eriFileSource;
+        this.mEriFile = new EriFile();
+    }
+
+    public void dispose() {
+        mEriFile = new EriFile();
+        isEriFileLoaded = false;
+    }
+
+
+    public void loadEriFile() {
+        switch (mEriFileSource) {
+        case ERI_FROM_MODEM:
+            loadEriFileFromModem();
+            break;
+
+        case ERI_FROM_FILE_SYSTEM:
+            loadEriFileFromFileSystem();
+            break;
+
+        case ERI_FROM_XML:
+        default:
+            loadEriFileFromXml();
+            break;
+        }
+    }
+
+    /**
+     * Load the ERI file from the MODEM through chipset specific RIL_REQUEST_OEM_HOOK
+     *
+     * In this case the ERI file can be updated from the Phone Support Tool available
+     * from the Chipset vendor
+     */
+    private void loadEriFileFromModem() {
+        // NOT IMPLEMENTED, Chipset vendor/Operator specific
+    }
+
+    /**
+     * Load the ERI file from a File System file
+     *
+     * In this case the a Phone Support Tool to update the ERI file must be provided
+     * to the Operator
+     */
+    private void loadEriFileFromFileSystem() {
+        // NOT IMPLEMENTED, Chipset vendor/Operator specific
+    }
+
+    /**
+     * Load the ERI file from the application framework resources encoded in XML
+     *
+     */
+    private void loadEriFileFromXml() {
+        Resources r = mContext.getResources();
+        XmlResourceParser parser = r.getXml(com.android.internal.R.xml.eri);
+        try {
+            XmlUtils.beginDocument(parser, "EriFile");
+            mEriFile.mVersionNumber = Integer.parseInt(
+                    parser.getAttributeValue(null, "VersionNumber"));
+            mEriFile.mNumberOfEriEntries = Integer.parseInt(
+                    parser.getAttributeValue(null, "NumberOfEriEntries"));
+            mEriFile.mEriFileType = Integer.parseInt(
+                    parser.getAttributeValue(null, "EriFileType"));
+
+            int parsedEriEntries = 0;
+            while(true) {
+                XmlUtils.nextElement(parser);
+                String name = parser.getName();
+                if (name == null) {
+                    if (parsedEriEntries != mEriFile.mNumberOfEriEntries)
+                        Log.e(LOG_TAG, "Error Parsing ERI file: " +  mEriFile.mNumberOfEriEntries
+                                + " defined, " + parsedEriEntries + " parsed!");
+                    break;
+                } else if (name.equals("CallPromptId")) {
+                    int id = Integer.parseInt(parser.getAttributeValue(null, "Id"));
+                    String text = parser.getAttributeValue(null, "CallPromptText");
+                    if (id >= 0 && id <= 2) {
+                        mEriFile.mCallPromptId[id] = text;
+                    } else {
+                        Log.e(LOG_TAG, "Error Parsing ERI file: found" + id + " CallPromptId");
+                    }
+
+                } else if (name.equals("EriInfo")) {
+                    int roamingIndicator = Integer.parseInt(
+                            parser.getAttributeValue(null, "RoamingIndicator"));
+                    int iconIndex = Integer.parseInt(parser.getAttributeValue(null, "IconIndex"));
+                    int iconMode = Integer.parseInt(parser.getAttributeValue(null, "IconMode"));
+                    String eriText = parser.getAttributeValue(null, "EriText");
+                    int callPromptId = Integer.parseInt(
+                            parser.getAttributeValue(null, "CallPromptId"));
+                    int alertId = Integer.parseInt(parser.getAttributeValue(null, "AlertId"));
+                    parsedEriEntries++;
+                    mEriFile.mRoamIndTable.put(roamingIndicator, new EriInfo (roamingIndicator,
+                            iconIndex, iconMode, eriText, callPromptId, alertId));
+                }
+            }
+
+            isEriFileLoaded = true;
+
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Got exception while loading ERI file.", e);
+        } finally {
+            parser.close();
+        }
+    }
+
+    /**
+     * Returns the version of the ERI file
+     *
+     */
+    public int getEriFileVersion() {
+        return mEriFile.mVersionNumber;
+    }
+
+    /**
+     * Returns the number of ERI entries parsed
+     *
+     */
+    public int getEriNumberOfEntries() {
+        return mEriFile.mNumberOfEriEntries;
+    }
+
+    /**
+     * Returns the ERI file type value ( 0 for Phase 0, 1 for Phase 1)
+     *
+     */
+    public int getEriFileType() {
+        return mEriFile.mEriFileType;
+    }
+
+    /**
+     * Returns if the ERI file has been loaded
+     *
+     */
+    public boolean isEriFileLoaded() {
+        return isEriFileLoaded;
+    }
+
+    /**
+     * Returns the EriInfo record associated with roamingIndicator
+     * or null if the entry is not found
+     */
+    public EriInfo getEriInfo(int roamingIndicator) {
+        if (mEriFile.mRoamIndTable.containsKey(roamingIndicator)) {
+            return mEriFile.mRoamIndTable.get(roamingIndicator);
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
index 9de6c42..3e2a29b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
@@ -68,7 +68,12 @@
     }
 
     protected String getEFPath(int efid) {
-        // TODO(): Implement for CDMA EFs.
+        switch(efid) {
+        case EF_SMS:
+        case EF_CST:
+        case EF_RUIM_SPN:
+            return MF_SIM + DF_CDMA;
+        }
         return getCommonIccEFPath(efid);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index b18a3f1..321824f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -49,13 +49,12 @@
     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
+    private String mImsi;       // TODO(Teleca): to be checked, if this should be removed!
+    private String mMyMobileNumber;
+    private String mSid;        // TODO(Teleca): Unused should this be removed
+    private String mNid;        // TODO(Teleca): Unused should this be removed
+    private String mMin2Min1;
 
     //***** Event Constants
 
@@ -63,6 +62,7 @@
     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_NV_READY = 9;
     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;
@@ -74,8 +74,6 @@
 
     private static final int EVENT_RUIM_REFRESH = 31;
 
-    //***** Constructor
-
     RuimRecords(CDMAPhone p) {
         super(p);
 
@@ -88,6 +86,7 @@
 
 
         p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
+        p.mCM.registerForNVReady(this, EVENT_NV_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);
@@ -104,10 +103,12 @@
         phone.mCM.unSetOnIccRefresh(this);
     }
 
+    @Override
     protected void finalize() {
         if(DBG) Log.d(LOG_TAG, "RuimRecords finalized");
     }
 
+    @Override
     protected void onRadioOffOrNotAvailable() {
         countVoiceMessages = 0;
         mncLength = 0;
@@ -124,17 +125,20 @@
         recordsRequested = false;
     }
 
-    //***** Public Methods
-
     /** Returns null if RUIM is not yet ready */
     public String getIMSI_M() {
-        return imsi_m;
+        return mImsi;
     }
 
     public String getMdnNumber() {
-        return mdn;
+        return mMyMobileNumber;
     }
 
+    public String getMin() {
+         return mMin2Min1;
+    }
+
+    @Override
     public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
         // In CDMA this is Operator/OEM dependent
         AsyncResult.forMessage((onComplete)).exception =
@@ -148,6 +152,7 @@
      * @param fileChanged indicates whether any files changed
      * @param fileList if non-null, a list of EF files that changed
      */
+    @Override
     public void onRefresh(boolean fileChanged, int[] fileList) {
         if (fileChanged) {
             // A future optimization would be to inspect fileList and
@@ -157,11 +162,12 @@
         }
     }
 
-    /** Returns the 5 or 6 digit MCC/MNC of the operator that
+    /** 
+     * 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) {
+    public String getRUIMOperatorNumeric() {
+        if (mImsi == null) {
             return null;
         }
 
@@ -169,7 +175,7 @@
             // 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);
+            return mImsi.substring(0, 3 + mncLength);
         }
 
         // Guess the MNC length based on the MCC if we don't
@@ -177,12 +183,12 @@
 
         int mcc;
 
-        mcc = Integer.parseInt(imsi_m.substring(0,3));
+        mcc = Integer.parseInt(mImsi.substring(0,3));
 
-        return imsi_m.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
+        return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
     }
 
-    //***** Overridden from Handler
+    @Override
     public void handleMessage(Message msg) {
         AsyncResult ar;
 
@@ -194,7 +200,9 @@
             case EVENT_RUIM_READY:
                 onRuimReady();
             break;
-
+            case EVENT_NV_READY:
+                onNvReady();
+            break;
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                 onRadioOffOrNotAvailable();
             break;
@@ -212,14 +220,12 @@
                     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];
-                }
+                mMyMobileNumber = localTemp[0];
+                mSid = localTemp[1];
+                mNid = localTemp[2];
+                mMin2Min1 = localTemp[3];
 
-                Log.d(LOG_TAG, "MDN: " + mdn);
+                Log.d(LOG_TAG, "MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
 
             break;
 
@@ -277,6 +283,7 @@
         }
     }
 
+    @Override
     protected void onRecordLoaded() {
         // One record loaded successfully or failed, In either case
         // we need to update the recordsToLoad count
@@ -290,6 +297,7 @@
         }
     }
 
+    @Override
     protected void onAllRecordsLoaded() {
         Log.d(LOG_TAG, "RuimRecords: record load complete");
 
@@ -301,9 +309,6 @@
                 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
@@ -318,6 +323,11 @@
 
     }
 
+    private void onNvReady() {
+        phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
+
+    }
+
     private void fetchRuimRecords() {
         recordsRequested = true;
 
@@ -391,9 +401,9 @@
         }
     }
 
+    @Override
     protected void log(String s) {
         Log.d(LOG_TAG, "[RuimRecords] " + s);
     }
 
 }
-
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index a2d3c5e..4fe1ea0 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -34,6 +34,7 @@
 import android.telephony.CellLocation;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -285,9 +286,8 @@
         return mDataConnection.getActiveApnString();
     }
 
-    public int
-    getSignalStrengthASU() {
-        return mSST.rssi == 99 ? -1 : mSST.rssi;
+    public SignalStrength getSignalStrength() {
+        return mSST.mSignalStrength;
     }
 
     public boolean
@@ -825,6 +825,11 @@
     }
 
     public void
+    sendBurstDtmf(String dtmfString) {
+        Log.e(LOG_TAG, "[GSMPhone] sendBurstDtmf() is a CDMA method");
+    }
+
+    public void
     setRadioPower(boolean power) {
         mSST.setRadioPower(power);
     }
@@ -872,6 +877,11 @@
         return ret;
     }
 
+    public String getMin() {
+        Log.e(LOG_TAG, "[GSMPhone] getMin() is a CDMA method");
+        return "0";
+    }
+
     public String getDeviceId() {
         return mImei;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 9e6ebc4..1d7aaf1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -50,6 +50,7 @@
 import android.util.EventLog;
 import android.util.Log;
 
+import com.android.internal.telephony.DataCallState;
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.DataConnection.FailCause;
 import com.android.internal.telephony.DataConnectionTracker;
@@ -779,7 +780,7 @@
     }
 
     private boolean
-    pdpStatesHasCID (ArrayList<PDPContextState> states, int cid) {
+    pdpStatesHasCID (ArrayList<DataCallState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
             if (states.get(i).cid == cid) return true;
         }
@@ -788,9 +789,11 @@
     }
 
     private boolean
-    pdpStatesHasActiveCID (ArrayList<PDPContextState> states, int cid) {
+    pdpStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
-            if (states.get(i).cid == cid) return (states.get(i).active != 0);
+            if ((states.get(i).cid == cid) && (states.get(i).active != 0)) {
+                return true;
+            }
         }
 
         return false;
@@ -825,9 +828,9 @@
      * previous state
      */
     protected void onPdpStateChanged (AsyncResult ar, boolean explicitPoll) {
-        ArrayList<PDPContextState> pdpStates;
+        ArrayList<DataCallState> pdpStates;
 
-        pdpStates = (ArrayList<PDPContextState>)(ar.result);
+        pdpStates = (ArrayList<DataCallState>)(ar.result);
 
         if (ar.exception != null) {
             // This is probably "radio not available" or something
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 9ab1002..7a4ea64 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -38,6 +38,7 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Telephony.Intents;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 import android.util.Config;
@@ -73,6 +74,14 @@
  * {@hide}
  */
 final class GsmServiceStateTracker extends ServiceStateTracker {
+
+    /**
+     * TODO(Teleca): John Huang asks: Will you be adding handling of
+     * "reason for registration denied in EVENT_POLL_STATE_REGISTRATION?
+     * I see some handling of this in CdmaServiceStateTracker, but as I
+     * understand it this field was added at the request of a GSM carrier.
+     */
+
     //***** Instance Variables
     GSMPhone phone;
     GsmCellLocation cellLoc;
@@ -80,9 +89,6 @@
     int mPreferredNetworkType;
     RestrictedState rs;
 
-    int rssi = 99;     // signal strength 0-31, 99=unknown
-                       // That's "received signal strength indication" fyi
-
     private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
     private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
 
@@ -121,7 +127,7 @@
     private boolean mStartedGprsRegCheck = false;
     // Already sent the event-log for no gprs register
     private boolean mReportedGprsNoReg = false;
-    
+
     /**
      * The Notification object given to the NotificationManager.
      */
@@ -151,9 +157,9 @@
     static final int CS_DISABLED = 1004;            // Access Control enables all voice/sms service
     static final int CS_NORMAL_ENABLED = 1005;      // Access Control blocks normal voice/sms service
     static final int CS_EMERGENCY_ENABLED = 1006;   // Access Control blocks emergency call service
-    
+
     // notification id
-    static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted 
+    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
 
     private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
@@ -177,6 +183,7 @@
         cellLoc = new GsmCellLocation();
         newCellLoc = new GsmCellLocation();
         rs = new RestrictedState();
+        mSignalStrength = new SignalStrength();
 
         PowerManager powerManager =
                 (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
@@ -201,7 +208,7 @@
         cr.registerContentObserver(
                 Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
                 mAutoTimeObserver);
-        setRssiDefaultValues();
+        setSignalStrengthDefaultValues();
         mNeedToRegForSimLoaded = true;
     }
 
@@ -280,7 +287,7 @@
      * @param obj placed in Message.obj
      */
     /*protected*/  void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
-        Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled "); 
+        Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
         Registrant r = new Registrant(h, what, obj);
         psRestrictEnabledRegistrants.add(r);
 
@@ -300,7 +307,7 @@
      * @param obj placed in Message.obj
      */
     /*protected*/  void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
-        Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled "); 
+        Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
         Registrant r = new Registrant(h, what, obj);
         psRestrictDisabledRegistrants.add(r);
 
@@ -308,7 +315,7 @@
             r.notifyRegistrant();
         }
     }
-    
+
     /*protected*/  void unregisterForPsRestrictedDisabled(Handler h) {
         psRestrictDisabledRegistrants.remove(h);
     }
@@ -506,13 +513,13 @@
                 }
                 mStartedGprsRegCheck = false;
                 break;
-                
+
             case EVENT_RESTRICTED_STATE_CHANGED:
                 // This is a notification from
                 // CommandsInterface.setOnRestrictedStateChanged
 
                 Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_RESTRICTED_STATE_CHANGED");
-                
+
                 ar = (AsyncResult) msg.obj;
 
                 onRestrictedStateChanged(ar);
@@ -542,11 +549,11 @@
                 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 
+                if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
                         && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
                     Log.d(LOG_TAG, "Data shutdown complete.");
                     break;
@@ -557,7 +564,7 @@
             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();
@@ -699,9 +706,8 @@
 
     }
 
-    private void
-    setRssiDefaultValues() {
-        rssi = 99;
+    private void setSignalStrengthDefaultValues() {
+        mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, true);
     }
 
     /**
@@ -722,7 +728,7 @@
             case RADIO_UNAVAILABLE:
                 newSS.setStateOutOfService();
                 newCellLoc.setStateInvalid();
-                setRssiDefaultValues();
+                setSignalStrengthDefaultValues();
                 mGotCountryCode = false;
 
                 pollStateDone();
@@ -731,7 +737,7 @@
             case RADIO_OFF:
                 newSS.setStateOff();
                 newCellLoc.setStateInvalid();
-                setRssiDefaultValues();
+                setSignalStrengthDefaultValues();
                 mGotCountryCode = false;
 
                 pollStateDone();
@@ -745,10 +751,10 @@
                 Log.d(LOG_TAG, "Radio Technology Change ongoing, setting SS to off");
                 newSS.setStateOff();
                 newCellLoc.setStateInvalid();
-                setRssiDefaultValues();
+                setSignalStrengthDefaultValues();
                 mGotCountryCode = false;
 
-                pollStateDone();
+                //NOTE: pollStateDone() is not needed in this case
                 break;
 
             default:
@@ -1044,17 +1050,18 @@
     }
 
     /**
-     *  send signal-strength-changed notification if rssi changed
+     *  send signal-strength-changed notification if changed
      *  Called both for solicited and unsolicited signal stength updates
      */
     private void
     onSignalStrengthResult(AsyncResult ar) {
-        int oldRSSI = rssi;
+        SignalStrength oldSignalStrength = mSignalStrength;
+        int rssi = 99;
 
         if (ar.exception != null) {
-            // 99 = unknown
+            // -1 = unknown
             // most likely radio is resetting/disconnected
-            rssi = 99;
+            setSignalStrengthDefaultValues();
         } else {
             int[] ints = (int[])ar.result;
 
@@ -1067,13 +1074,16 @@
             }
         }
 
-        if (rssi != oldRSSI) {
+        mSignalStrength = new SignalStrength(rssi, -1, -1, -1,
+                -1, -1, -1, true);
+
+        if (!mSignalStrength.equals(oldSignalStrength)) {
             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");
+                log("onSignalStrengthResult() Phone already destroyed: " + ex
+                        + "SignalStrength not notified");
            }
         }
     }
@@ -1089,27 +1099,27 @@
     {
         Log.d(LOG_TAG, "[DSAC DEB] " + "onRestrictedStateChanged");
         RestrictedState newRs = new RestrictedState();
- 
+
         Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at enter "+ rs);
-        
+
         if (ar.exception == null) {
             int[] ints = (int[])ar.result;
             int state = ints[0];
-            
+
             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.getIccCard().getState() == IccCard.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) );
                 newRs.setPsRestricted(
                         (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
             }
-            
-            Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);         
-            
+
+            Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);
+
             if (!rs.isPsRestricted() && newRs.isPsRestricted()) {
                 psRestrictEnabledRegistrants.notifyRegistrants();
                 setNotification(PS_ENABLED);
@@ -1117,9 +1127,9 @@
                 psRestrictDisabledRegistrants.notifyRegistrants();
                 setNotification(PS_DISABLED);
             }
-            
+
             /**
-             * There are two kind of cs restriction, normal and emergency. So 
+             * There are two kind of cs restriction, normal and emergency. So
              * there are 4 x 4 combinations in current and new restricted states
              * and we only need to notify when state is changed.
              */
@@ -1129,32 +1139,32 @@
                     setNotification(CS_DISABLED);
                 } else if (!newRs.isCsNormalRestricted()) {
                     // remove normal restriction
-                    setNotification(CS_EMERGENCY_ENABLED); 
+                    setNotification(CS_EMERGENCY_ENABLED);
                 } else if (!newRs.isCsEmergencyRestricted()) {
                     // remove emergency restriction
-                    setNotification(CS_NORMAL_ENABLED); 
+                    setNotification(CS_NORMAL_ENABLED);
                 }
             } else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) {
                 if (!newRs.isCsRestricted()) {
                     // remove all restriction
-                    setNotification(CS_DISABLED); 
+                    setNotification(CS_DISABLED);
                 } else if (newRs.isCsRestricted()) {
                     // enable all restriction
                     setNotification(CS_ENABLED);
                 } else if (newRs.isCsNormalRestricted()) {
                     // remove emergency restriction and enable normal restriction
-                    setNotification(CS_NORMAL_ENABLED); 
+                    setNotification(CS_NORMAL_ENABLED);
                 }
             } else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) {
                 if (!newRs.isCsRestricted()) {
                     // remove all restriction
-                    setNotification(CS_DISABLED); 
+                    setNotification(CS_DISABLED);
                 } else if (newRs.isCsRestricted()) {
                     // enable all restriction
                     setNotification(CS_ENABLED);
                 } else if (newRs.isCsEmergencyRestricted()) {
                     // remove normal restriction and enable emergency restriction
-                    setNotification(CS_EMERGENCY_ENABLED); 
+                    setNotification(CS_EMERGENCY_ENABLED);
                 }
             } else {
                 if (newRs.isCsRestricted()) {
@@ -1162,10 +1172,10 @@
                     setNotification(CS_ENABLED);
                 } else if (newRs.isCsEmergencyRestricted()) {
                     // enable emergency restriction
-                    setNotification(CS_EMERGENCY_ENABLED); 
+                    setNotification(CS_EMERGENCY_ENABLED);
                 } else if (newRs.isCsNormalRestricted()) {
                     // enable normal restriction
-                    setNotification(CS_NORMAL_ENABLED); 
+                    setNotification(CS_NORMAL_ENABLED);
                 }
             }
 
@@ -1527,7 +1537,7 @@
 
     /**
      * Post a notification to NotificationManager for restricted state
-     * 
+     *
      * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE
      */
     private void setNotification(int notifyType) {
@@ -1546,7 +1556,7 @@
         CharSequence details = "";
         CharSequence title = context.getText(com.android.internal.R.string.RestrictedChangedTitle);
         int notificationId = CS_NOTIFICATION;
-        
+
         switch (notifyType) {
         case PS_ENABLED:
             notificationId = PS_NOTIFICATION;
@@ -1557,24 +1567,24 @@
             break;
         case CS_ENABLED:
             details = context.getText(com.android.internal.R.string.RestrictedOnAll);;
-            break;   
+            break;
         case CS_NORMAL_ENABLED:
             details = context.getText(com.android.internal.R.string.RestrictedOnNormal);;
-            break;   
+            break;
         case CS_EMERGENCY_ENABLED:
             details = context.getText(com.android.internal.R.string.RestrictedOnEmergency);;
-            break;   
+            break;
         case CS_DISABLED:
             // do nothing and cancel the notification later
-            break;  
+            break;
         }
-        
+
         Log.d(LOG_TAG, "[DSAC DEB] " + "put notification " + title + " / " +details);
         mNotification.tickerText = title;
-        mNotification.setLatestEventInfo(context, title, details, 
+        mNotification.setLatestEventInfo(context, title, details,
                 mNotification.contentIntent);
-        
-        NotificationManager notificationManager = (NotificationManager) 
+
+        NotificationManager notificationManager = (NotificationManager)
             context.getSystemService(Context.NOTIFICATION_SERVICE);
 
         if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
@@ -1585,4 +1595,8 @@
             notificationManager.notify(notificationId, mNotification);
         }
     }
+
+    private void log(String s) {
+        Log.d(LOG_TAG, "[GsmServiceStateTracker] " + s);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/MccTable.java b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
index 6198979..e18da56 100644
--- a/telephony/java/com/android/internal/telephony/gsm/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
@@ -182,7 +182,7 @@
 		table.add(new MccEntry(222,"it",2,"Europe/Rome","it"));	//Italy
 		table.add(new MccEntry(225,"va",2,"Europe/Rome","it"));	//Vatican City State
 		table.add(new MccEntry(226,"ro",2));	//Romania
-		table.add(new MccEntry(228,"ch",2,"Europe/Zurich","en"));	//Switzerland (Confederation of)
+		table.add(new MccEntry(228,"ch",2,"Europe/Zurich","de"));	//Switzerland (Confederation of)
 		table.add(new MccEntry(230,"cz",2,"Europe/Prague","cs"));	//Czech Republic
 		table.add(new MccEntry(231,"sk",2));	//Slovak Republic
 		table.add(new MccEntry(232,"at",2,"Europe/Vienna","de"));	//Austria
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index 5c69017..42bb2e0 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -26,8 +26,8 @@
 import com.android.internal.telephony.BaseCommands;
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataCallState;
 import com.android.internal.telephony.gsm.CallFailCause;
-import com.android.internal.telephony.gsm.PDPContextState;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 import com.android.internal.telephony.Phone;
 
@@ -59,7 +59,7 @@
     private final static String SIM_PUK2_CODE = "87654321";
 
     //***** Instance Variables
-    
+
     SimulatedGsmCallState simulatedCallState;
     HandlerThread mHandlerThread;
     SimLockState mSimLockedState;
@@ -79,7 +79,7 @@
     ArrayList<Message> pausedResponses = new ArrayList<Message>();
 
     int nextCallFailCause = CallFailCause.NORMAL_CLEARING;
-    
+
     //***** Constructor
 
     public
@@ -88,9 +88,9 @@
         mHandlerThread = new HandlerThread("SimulatedCommands");
         mHandlerThread.start();
         Looper looper = mHandlerThread.getLooper();
-        
+
         simulatedCallState = new SimulatedGsmCallState(looper);
-        
+
         setRadioState(RadioState.RADIO_OFF);
         mSimLockedState = INITIAL_LOCK_STATE;
         mSimLockEnabled = (mSimLockedState != SimLockState.NONE);
@@ -353,11 +353,11 @@
     public void
     setSuppServiceNotifications(boolean enable, Message result) {
         resultSuccess(result, null);
-        
+
         if (enable && mSsnNotifyOn) {
             Log.w(LOG_TAG, "Supp Service Notifications already enabled!");
         }
-        
+
         mSsnNotifyOn = enable;
     }
 
@@ -465,7 +465,7 @@
         unimplemented(result);
     }
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -479,13 +479,13 @@
             resultSuccess(result, simulatedCallState.getDriverCalls());
         } else {
             //Log.i("GSM", "[SimCmds] getCurrentCalls: SIM not ready!");
-            resultFail(result, 
+            resultFail(result,
                 new CommandException(
                     CommandException.Error.RADIO_NOT_AVAILABLE));
         }
     }
 
-    /** 
+    /**
      *  @deprecated
      */
     public void getPDPContextList(Message result) {
@@ -497,13 +497,13 @@
      *  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
+     *  ar.result contains a List of DataCallState
      */
     public void getDataCallList(Message result) {
-        resultSuccess(result, new ArrayList<PDPContextState>(0));
+        resultSuccess(result, new ArrayList<DataCallState>(0));
     }
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -520,7 +520,7 @@
         resultSuccess(result, null);
     }
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -531,7 +531,7 @@
         resultSuccess(result, "012345678901234");
     }
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -542,7 +542,7 @@
         resultSuccess(result, "012345678901234");
     }
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -553,7 +553,7 @@
         resultSuccess(result, "99");
     }
 
-    /** 
+    /**
      * Hang up one individual connection.
      *  returned message
      *  retMsg.obj = AsyncResult ar
@@ -566,7 +566,7 @@
      */
     public void hangupConnection (int gsmIndex, Message result) {
         boolean success;
-        
+
         success = simulatedCallState.onChld('1', (char)('0'+gsmIndex));
 
         if (!success){
@@ -588,7 +588,7 @@
      */
     public void hangupWaitingOrBackground (Message result) {
         boolean success;
-        
+
         success = simulatedCallState.onChld('0', '\0');
 
         if (!success){
@@ -600,7 +600,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
@@ -609,7 +609,7 @@
      */
     public void hangupForegroundResumeBackground (Message result) {
         boolean success;
-        
+
         success = simulatedCallState.onChld('1', '\0');
 
         if (!success){
@@ -621,7 +621,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
@@ -630,7 +630,7 @@
      */
     public void switchWaitingOrHoldingAndActive (Message result) {
         boolean success;
-        
+
         success = simulatedCallState.onChld('2', '\0');
 
         if (!success){
@@ -647,10 +647,10 @@
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     public void conference (Message result) {
         boolean success;
-        
+
         success = simulatedCallState.onChld('3', '\0');
 
         if (!success){
@@ -682,7 +682,7 @@
 
     /**
      * 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."
      */
     public void separateConnection (int gsmIndex, Message result) {
@@ -703,10 +703,10 @@
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     public void acceptCall (Message result) {
         boolean success;
-        
+
         success = simulatedCallState.onAnswer();
 
         if (!success){
@@ -716,15 +716,15 @@
         }
     }
 
-    /** 
+    /**
      *  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
-     */    
+     */
     public void rejectCall (Message result) {
         boolean success;
-        
+
         success = simulatedCallState.onChld('0', '\0');
 
         if (!success){
@@ -734,7 +734,7 @@
         }
     }
 
-    /** 
+    /**
      * cause code returned as Integer in Message.obj.response
      * Returns integer cause code defined in TS 24.008
      * Annex H or closest approximation.
@@ -765,11 +765,11 @@
 
     public void getMute (Message result) {unimplemented(result);}
 
-    /** 
+    /**
      * 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
      */
     public void getSignalStrength (Message result) {
@@ -893,7 +893,7 @@
      * 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
-     */ 
+     */
     public void getOperator(Message result) {
         String[] ret = new String[3];
 
@@ -908,7 +908,7 @@
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     public void sendDtmf(char c, Message result) {
         resultSuccess(result, null);
     }
@@ -932,10 +932,19 @@
     }
 
     /**
+     *  ar.exception carries exception on failure
+     *  ar.userObject contains the orignal value of result.obj
+     *  ar.result is null on success and failure
+     */
+    public void sendBurstDtmf(String dtmfString, Message result) {
+        resultSuccess(result, null);
+    }
+
+    /**
      * 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
      */
     public void sendSMS (String smscPDU, String pdu, Message result) {unimplemented(result);}
 
@@ -1040,8 +1049,8 @@
         unimplemented(result);
     }
 
-    /** 
-     * parameters equivilient to 27.007 AT+CRSM command 
+    /**
+     * parameters equivilient to 27.007 AT+CRSM command
      * response.obj will be an AsyncResult
      * response.obj.userObj will be a SimIoResult on success
      */
@@ -1052,7 +1061,7 @@
 
     /**
      * (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
      */
@@ -1063,46 +1072,46 @@
      * 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
      */
 
     public void getCLIR(Message result) {unimplemented(result);}
-    
+
     /**
      * clirMode is one of the CLIR_* constants above
      *
      * response.obj is null
      */
-    
+
     public void setCLIR(int clirMode, Message result) {unimplemented(result);}
 
     /**
      * (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
      */
-    
+
     public void queryCallWaiting(int serviceClass, Message response) {
         unimplemented(response);
     }
-    
+
     /**
      * @param enable is true to enable, false to disable
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    
+
     public void setCallWaiting(boolean enable, int serviceClass,
             Message response) {
         unimplemented(response);
@@ -1111,9 +1120,9 @@
     /**
      * @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_*
      */
-    public void setCallForward(int action, int cfReason, int serviceClass, 
+    public void setCallForward(int action, int cfReason, int serviceClass,
             String number, int timeSeconds, Message result) {unimplemented(result);}
 
     /**
@@ -1121,7 +1130,7 @@
      *
      * ((AsyncResult)response.obj).result will be an array of
      * CallForwardInfo's
-     * 
+     *
      * An array of length 0 means "disabled for all codes"
      */
     public void queryCallForwardStatus(int cfReason, int serviceClass,
@@ -1155,7 +1164,7 @@
     public void getAvailableNetworks(Message result) {unimplemented(result);}
 
     public void getBasebandVersion (Message result) {
-        resultSuccess(result, "SimulatedCommands"); 
+        resultSuccess(result, "SimulatedCommands");
     }
 
     /**
@@ -1167,7 +1176,7 @@
     public void triggerIncomingUssd(String statusCode, String message) {
         if (mUSSDRegistrant != null) {
             String[] result = {statusCode, message};
-            mUSSDRegistrant.notifyResult(result);            
+            mUSSDRegistrant.notifyResult(result);
         }
     }
 
@@ -1215,7 +1224,7 @@
 
     //***** SimulatedRadioControl
 
-    
+
     /** Start the simulated phone ringing */
     public void
     triggerRing(String number) {
@@ -1249,9 +1258,9 @@
         simulatedCallState.setNextDialFailImmediately(b);
     }
 
-    public void 
+    public void
     setNextCallFailCause(int gsmCause) {
-        nextCallFailCause = gsmCause;    
+        nextCallFailCause = gsmCause;
     }
 
     public void
@@ -1319,7 +1328,7 @@
 
     private void unimplemented(Message result) {
         if (result != null) {
-            AsyncResult.forMessage(result).exception 
+            AsyncResult.forMessage(result).exception
                 = new RuntimeException("Unimplemented");
 
             if (pausedResponseCount > 0) {
@@ -1359,13 +1368,13 @@
         unimplemented(response);
     }
 
-    public void 
+    public void
     getCDMASubscription(Message response) {
         Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
         unimplemented(response);
     }
 
-    public void 
+    public void
     setCdmaSubscription(int cdmaSubscriptionType, Message response) {
         Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
         unimplemented(response);
@@ -1403,7 +1412,7 @@
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    public void setTTYModeEnabled(boolean enable, Message response) {
+    public void setTTYMode(int ttyMode, Message response) {
         Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
         unimplemented(response);
     }
@@ -1411,12 +1420,12 @@
     /**
      *  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. 
-     *  
+     * 0 for disabled, 1 for enabled.
+     *
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    public void queryTTYModeEnabled(Message response) {
+    public void queryTTYMode(Message response) {
         Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
         unimplemented(response);
     }
@@ -1451,4 +1460,11 @@
 
     }
 
+    public void exitEmergencyCallbackMode(Message response) {
+        // TODO method stub
+    }
+
+    public void forceDataDormancy(Message response) {
+        // TODO method stub
+    }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java
index 8b6cad1..f623080 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java
@@ -510,7 +510,8 @@
         mDatabase.execSQL("CREATE TABLE tokens (" +
                 "token TEXT COLLATE unicode," +
                 "source INTEGER," +
-                "token_index INTEGER" +
+                "token_index INTEGER," +
+                "tag TEXT" +
                 ");");
         mDatabase.execSQL("CREATE TABLE tokens_no_index (" +
                 "token TEXT COLLATE unicode," +
@@ -527,8 +528,10 @@
                 "SELECT _TOKENIZE('tokens', 10, 'some string', NULL)", null));
      
         Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, 
-                "SELECT _TOKENIZE('tokens', 11, 'some string ok', ' ', 1)", null));
-        
+                "SELECT _TOKENIZE('tokens', 11, 'some string ok', ' ', 1, 'foo')", null));
+        Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
+                "SELECT _TOKENIZE('tokens', 11, 'second field', ' ', 1, 'bar')", null));
+
         Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
                 "SELECT _TOKENIZE('tokens_no_index', 20, 'some string ok', ' ')", null));
         Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
@@ -544,7 +547,7 @@
         Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, 
                 "SELECT _TOKENIZE('tokens', 13, '" + icustr + "', ' ', 1)", null));
         
-        Assert.assertEquals(7, DatabaseUtils.longForQuery(mDatabase, 
+        Assert.assertEquals(9, DatabaseUtils.longForQuery(mDatabase,
                 "SELECT count(*) from tokens;", null));      
 
         String key = DatabaseUtils.getHexCollationKey("Frederic Hjonneva");
@@ -569,6 +572,8 @@
                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
+                "SELECT tag from tokens where token GLOB '" + key + "*'", null));
         key = DatabaseUtils.getHexCollationKey("string");
         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 
                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
@@ -576,6 +581,8 @@
                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
+                "SELECT tag from tokens where token GLOB '" + key + "*'", null));
         key = DatabaseUtils.getHexCollationKey("ok");
         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, 
                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
@@ -583,7 +590,28 @@
                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
         Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
-        
+        Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
+                "SELECT tag from tokens where token GLOB '" + key + "*'", null));
+
+        key = DatabaseUtils.getHexCollationKey("second field");
+        Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+                "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
+                "SELECT source from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
+                "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase,
+                "SELECT tag from tokens where token GLOB '" + key + "*'", null));
+        key = DatabaseUtils.getHexCollationKey("field");
+        Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+                "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
+                "SELECT source from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
+                "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
+        Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase,
+                "SELECT tag from tokens where token GLOB '" + key + "*'", null));
+
         key = DatabaseUtils.getHexCollationKey(chinese);
         String[] a = new String[1];
         a[0] = key;
diff --git a/tests/CoreTests/android/location/LocationManagerProximityTest.java b/tests/CoreTests/android/location/LocationManagerProximityTest.java
index 3f43bcf..e82d878 100644
--- a/tests/CoreTests/android/location/LocationManagerProximityTest.java
+++ b/tests/CoreTests/android/location/LocationManagerProximityTest.java
@@ -26,6 +26,7 @@
 import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
 /**
@@ -37,9 +38,11 @@
  *  adb shell am instrument -e class android.location.LocationManagerProximityTest \
  *     -w android.core/android.test.InstrumentationTestRunner
  *     
- * This test requires that the "Allow mock locations" setting be enabled     
+ * This test requires that the "Allow mock locations" setting be enabled.
+ * To ensure reliable results, all location providers should be disabled.
  * 
  */
+@Suppress
 @MediumTest
 public class LocationManagerProximityTest extends AndroidTestCase {
 
diff --git a/tests/sketch/AndroidManifest.xml b/tests/sketch/AndroidManifest.xml
index c44b54e..1f4333c 100755
--- a/tests/sketch/AndroidManifest.xml
+++ b/tests/sketch/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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,11 +14,12 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="com.android.gesture"
+      package="com.android.gesture.example"
       android:versionCode="1"
       android:versionName="1.0.0">
+      <uses-permission android:name="android.permission.READ_CONTACTS" />
       <application android:icon="@drawable/icon" android:label="@string/app_name">
-        <activity android:name="com.android.gesture.example.GestureEntryDemo"
+        <activity android:name="com.android.gesture.example.GestureEntry"
                   android:label="@string/app_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -26,5 +27,12 @@
             </intent-filter>
         </activity>
         <activity android:name="com.android.gesture.example.GestureLibViewer"/>
+        <activity android:name="com.android.gesture.example.ContactListGestureOverlay"
+                  android:label="@string/overlay_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest> 
diff --git a/tests/sketch/res/layout/demo.xml b/tests/sketch/res/layout/demo.xml
index e516229..8c9161a 100755
--- a/tests/sketch/res/layout/demo.xml
+++ b/tests/sketch/res/layout/demo.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
@@ -13,6 +13,7 @@
      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"
@@ -24,7 +25,7 @@
         android:drawSelectorOnTop="true"
         android:prompt="@string/recognition_result"/>
     
-    <com.android.gesture.GesturePad 
+    <com.android.gesture.GestureOverlay 
         android:id="@+id/drawingpad"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
diff --git a/tests/sketch/res/layout/gestureviewer.xml b/tests/sketch/res/layout/gestureviewer.xml
index 5302d34..73d6a35 100755
--- a/tests/sketch/res/layout/gestureviewer.xml
+++ b/tests/sketch/res/layout/gestureviewer.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
@@ -13,6 +13,7 @@
      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"
@@ -25,7 +26,7 @@
         android:drawSelectorOnTop="true"
         android:prompt="@string/recognition_result"/>
     
-    <com.android.gesture.GesturePad 
+    <com.android.gesture.GestureOverlay 
         android:id="@+id/drawingpad"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
diff --git a/tests/sketch/res/layout/newgesture_dialog.xml b/tests/sketch/res/layout/newgesture_dialog.xml
index 6e45d81..91e7645 100755
--- a/tests/sketch/res/layout/newgesture_dialog.xml
+++ b/tests/sketch/res/layout/newgesture_dialog.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
diff --git a/tests/sketch/res/layout/overlaydemo.xml b/tests/sketch/res/layout/overlaydemo.xml
new file mode 100644
index 0000000..b6bbab3
--- /dev/null
+++ b/tests/sketch/res/layout/overlaydemo.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+    <ListView
+      android:id="@+id/list" 
+      android:layout_width="fill_parent" 
+      android:layout_height="0dip"
+      android:layout_weight="1"/>
+</LinearLayout>
diff --git a/tests/sketch/res/values/strings.xml b/tests/sketch/res/values/strings.xml
index 4c6aa20..42f14da 100755
--- a/tests/sketch/res/values/strings.xml
+++ b/tests/sketch/res/values/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
@@ -15,6 +15,7 @@
 -->
 <resources>
     <string name="app_name">Gesture Demo</string>
+    <string name="overlay_name">Overlay Demo</string>  
     <string name="recognition_result">Recognition Result</string>
     <string name="clear">Clear</string>
     <string name="newgesture">Add</string>
diff --git a/tests/sketch/src/com/android/gesture/Gesture.java b/tests/sketch/src/com/android/gesture/Gesture.java
index 29c07ad..a5e7a25 100755
--- a/tests/sketch/src/com/android/gesture/Gesture.java
+++ b/tests/sketch/src/com/android/gesture/Gesture.java
@@ -18,343 +18,290 @@
 
 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.
+ * A gesture can have a single or multiple strokes
  */
 
 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; 
+    private static final long GESTURE_ID_BASE = System.currentTimeMillis();
+
+    private static final int BITMAP_RENDERING_WIDTH = 2;
+
+    private static final boolean BITMAP_RENDERING_ANTIALIAS = true;
+
+    private static final boolean BITMAP_RENDERING_DITHER = true;
+
+    private static int sGestureCount = 0;
+
+    private RectF mBoundingBox;
+
+    // the same as its instance ID
+    private long mGestureID;
+
+    private ArrayList<GestureStroke> mStrokes = new ArrayList<GestureStroke>();
 
     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();
+        mGestureID = GESTURE_ID_BASE + sGestureCount++;
     }
 
     /**
+     * @return all the strokes of the gesture
+     */
+    public ArrayList<GestureStroke> getStrokes() {
+        return mStrokes;
+    }
+
+    /**
+     * @return the number of strokes included by this gesture
+     */
+    public int getStrokesCount() {
+        return mStrokes.size();
+    }
+
+    /**
+     * Add a stroke to the gesture
+     * 
+     * @param stroke
+     */
+    public void addStroke(GestureStroke stroke) {
+        mStrokes.add(stroke);
+
+        if (mBoundingBox == null) {
+            mBoundingBox = new RectF(stroke.boundingBox);
+        } else {
+            mBoundingBox.union(stroke.boundingBox);
+        }
+    }
+
+    /**
+     * Get the total length of the gesture. When there are multiple strokes in
+     * the gesture, this returns the sum of the lengths of all the strokes
+     * 
      * @return the length of the gesture
      */
     public float getLength() {
-        return this.mLength;
+        int len = 0;
+        ArrayList<GestureStroke> strokes = mStrokes;
+        int count = strokes.size();
+        for (int i = 0; i < count; i++) {
+            GestureStroke stroke = strokes.get(i);
+            len += stroke.length;
+        }
+        return len;
     }
-  
-    public RectF getBBX() {
-        return mBBX;
+
+    /**
+     * @return the bounding box of the gesture
+     */
+    public RectF getBoundingBox() {
+        return mBoundingBox;
     }
-  
-    public void setID(long id) {
-        mID = id;
+
+    /**
+     * Set the id of the gesture
+     * 
+     * @param id
+     */
+    void setID(long id) {
+        mGestureID = id;
     }
-    
+
+    /**
+     * @return the id of the gesture
+     */
     public long getID() {
-        return mID;
+        return mGestureID;
     }
-    
-    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;
-            }
-          }
+    void draw(Canvas canvas, Paint paint) {
+        ArrayList<GestureStroke> strokes = mStrokes;
+        int count = strokes.size();
+        for (int i = 0; i < count; i++) {
+            GestureStroke stroke = strokes.get(i);
+            stroke.draw(canvas, paint);
         }
-        
-        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
+     * Create a bitmap of the gesture with a transparent background
+     * 
+     * @param width width of the target bitmap
+     * @param height height of the target bitmap
+     * @param edge the edge
      * @param numSample
-     * @param foreground
-     * @return
+     * @param color
+     * @return the bitmap
      */
-    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);
+    public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) {
+        RectF bbx = getBoundingBox();
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        canvas.translate(edge, edge);
         Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setDither(true);
-        paint.setColor(mColor);
+        paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
+        paint.setDither(BITMAP_RENDERING_DITHER);
+        paint.setColor(color);
         paint.setStyle(Paint.Style.STROKE);
         paint.setStrokeJoin(Paint.Join.ROUND);
         paint.setStrokeCap(Paint.Cap.ROUND);
-        paint.setStrokeWidth(2);
-        c.drawPath(path, paint);
+        paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
+        ArrayList<GestureStroke> strokes = mStrokes;
+        int count = strokes.size();
+        for (int i = 0; i < count; i++) {
+            GestureStroke stroke = strokes.get(i);
+            Path path = stroke.toPath(width - 2 * edge, height - 2 * edge, numSample);
+            canvas.drawPath(path, paint);
+        }
+
         return bitmap;
     }
-    
+
     /**
-     * save the gesture as XML
+     * Create a bitmap of the gesture with a transparent background
+     * 
+     * @param width
+     * @param height
+     * @param edge
+     * @param color
+     * @return the bitmap
+     */
+    public Bitmap toBitmap(int width, int height, int edge, int color) {
+        RectF bbx = getBoundingBox();
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        canvas.translate(edge, edge);
+        Paint paint = new Paint();
+        paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
+        paint.setDither(BITMAP_RENDERING_DITHER);
+        paint.setColor(color);
+        paint.setStyle(Paint.Style.STROKE);
+        paint.setStrokeJoin(Paint.Join.ROUND);
+        paint.setStrokeCap(Paint.Cap.ROUND);
+        paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
+        ArrayList<GestureStroke> strokes = mStrokes;
+        int count = strokes.size();
+        for (int i = 0; i < count; i++) {
+            GestureStroke stroke = strokes.get(i);
+            stroke.draw(canvas, 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;
+    void toXML(String namespace, XmlSerializer serializer) throws IOException {
+        serializer.startTag(namespace, GestureConstants.XML_TAG_GESTURE);
+        serializer.attribute(namespace, GestureConstants.XML_TAG_ID, Long.toString(mGestureID));
+        ArrayList<GestureStroke> strokes = mStrokes;
+        int count = strokes.size();
+        for (int i = 0; i < count; i++) {
+            GestureStroke stroke = strokes.get(i);
+            stroke.toXML(namespace, serializer);
         }
-        serializer.text(pts);
-        serializer.endTag(namespace, "stroke");
+        serializer.endTag(namespace, GestureConstants.XML_TAG_GESTURE);
     }
-    
-    
+
+    /**
+     * Create the gesture from a string
+     * 
+     * @param str
+     */
     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));
+        int startIndex = 0;
+        int endIndex;
+        while ((endIndex = str.indexOf(GestureConstants.STRING_GESTURE_DELIIMITER, startIndex + 1)) != -1) {
+            String token = str.substring(startIndex, endIndex);
+            if (startIndex > 0) { // stroke tokens
+                addStroke(GestureStroke.createFromString(token));
+            } else { // id token
+                mGestureID = Long.parseLong(token);
+            }
+            startIndex = endIndex + 1;
         }
-  
-        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);
     }
-    
+
+    /**
+     * Convert the gesture to string
+     */
     @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 + ","; 
+        StringBuilder str = new StringBuilder();
+        str.append(mGestureID);
+        ArrayList<GestureStroke> strokes = mStrokes;
+        int count = strokes.size();
+        for (int i = 0; i < count; i++) {
+            GestureStroke stroke = strokes.get(i);
+            str.append(GestureConstants.STRING_GESTURE_DELIIMITER);
+            str.append(stroke.toString());
         }
 
-        str += "#";
-        str += this.mColor;
-        
-        str += "#";
-        str += this.mWidth;
-        
-        str += "#";
-        str += this.mLength;
-        
-        str += "#";
-        str += this.mTimestamp;
-  
-        return str;
+        return str.toString();
     }
-    
-    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+
+    public static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() {
         public Gesture createFromParcel(Parcel in) {
             String str = in.readString();
-            Gesture stk = new Gesture();
-            stk.createFromString(str);
-            return stk;
+            Gesture gesture = new Gesture();
+            gesture.createFromString(str);
+            return gesture;
         }
-    
+
         public Gesture[] newArray(int size) {
             return new Gesture[size];
         }
     };
-    
-    public static Gesture buildFromArray(byte[] bytes) {
+
+    /**
+     * Build a gesture from a byte array
+     * 
+     * @param bytes
+     * @return the gesture
+     */
+    static Gesture buildFromArray(byte[] bytes) {
         String str = new String(bytes);
-        Gesture stk = new Gesture();
-        stk.createFromString(str);
-        return stk;
+        Gesture gesture = new Gesture();
+        gesture.createFromString(str);
+        return gesture;
     }
-    
-    public static byte[] saveToArray(Gesture stk) {
-        String str = stk.toString();   
+
+    /**
+     * Save a gesture to a byte array
+     * 
+     * @param stroke
+     * @return the byte array
+     */
+    static byte[] saveToArray(Gesture stroke) {
+        String str = stroke.toString();
         return str.getBytes();
     }
-    
+
     public void writeToParcel(Parcel out, int flags) {
-        out.writeString(this.toString());
+        out.writeString(toString());
     }
-      
+
     public int describeContents() {
         return CONTENTS_FILE_DESCRIPTOR;
     }
diff --git a/tests/sketch/src/com/android/gesture/GestureActionListener.java b/tests/sketch/src/com/android/gesture/GestureActionListener.java
new file mode 100644
index 0000000..130ac19
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureActionListener.java
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+
+public interface GestureActionListener {
+    public void onGesturePerformed(GestureOverlay overlay, Gesture gesture);
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureConstants.java b/tests/sketch/src/com/android/gesture/GestureConstants.java
new file mode 100644
index 0000000..0e17c8a
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureConstants.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gesture;
+
+interface GestureConstants {
+    static final String XML_TAG_LIBRARY = "library";
+    static final String XML_TAG_ENTRY = "entry";
+    static final String XML_TAG_GESTURE = "gesture";
+    static final String XML_TAG_STROKE = "stroke";
+    static final String XML_TAG_ID = "id";
+    static final String XML_TAG_NAME = "name";
+    static final String STRING_GESTURE_DELIIMITER = "#";
+    static final String STRING_STROKE_DELIIMITER = ",";
+    static final int STROKE_STRING_BUFFER_SIZE = 1024;
+    static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points
+    static final int IO_BUFFER_SIZE = 8 * 1024; // 8K
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureLib.java b/tests/sketch/src/com/android/gesture/GestureLib.java
deleted file mode 100755
index d0a25f2..0000000
--- a/tests/sketch/src/com/android/gesture/GestureLib.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-import android.util.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/tests/sketch/src/com/android/gesture/GestureLibrary.java b/tests/sketch/src/com/android/gesture/GestureLibrary.java
new file mode 100644
index 0000000..c89aa16
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureLibrary.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gesture;
+
+import android.util.Config;
+import android.util.Log;
+import android.util.Xml;
+import android.util.Xml.Encoding;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * GestureLibrary maintains gesture examples and makes predictions on a new
+ * gesture
+ */
+public class GestureLibrary {
+
+    public static final int SEQUENCE_INVARIANT = 1;
+
+    // when SEQUENCE_SENSITIVE is used, only single stroke gestures are allowed
+    public static final int SEQUENCE_SENSITIVE = 2;
+
+    private int mSequenceType = SEQUENCE_SENSITIVE;
+
+    public static final int ORIENTATION_INVARIANT = 1;
+
+    // ORIENTATION_SENSITIVE is only available for single stroke gestures
+    public static final int ORIENTATION_SENSITIVE = 2;
+
+    private int mOrientationStyle = ORIENTATION_SENSITIVE;
+
+    private static final String LOGTAG = "GestureLibrary";
+
+    private static final String NAMESPACE = "";
+
+    private final String mGestureFileName;
+
+    private HashMap<String, ArrayList<Gesture>> mEntryName2gestures = new HashMap<String, ArrayList<Gesture>>();
+
+    private Learner mClassifier;
+
+    private boolean mChanged = false;
+
+    /**
+     * @param path where gesture data is stored
+     */
+    public GestureLibrary(String path) {
+        mGestureFileName = path;
+        mClassifier = new InstanceLearner();
+    }
+
+    /**
+     * Specify whether the gesture library will handle orientation sensitive
+     * gestures. Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
+     * 
+     * @param style
+     */
+    public void setOrientationStyle(int style) {
+        mOrientationStyle = style;
+    }
+
+    public int getOrientationStyle() {
+        return mOrientationStyle;
+    }
+
+    public void setGestureType(int type) {
+        mSequenceType = type;
+    }
+
+    public int getGestureType() {
+        return mSequenceType;
+    }
+
+    /**
+     * Get all the gesture entry names in the library
+     * 
+     * @return a set of strings
+     */
+    public Set<String> getGestureEntries() {
+        return mEntryName2gestures.keySet();
+    }
+
+    /**
+     * Recognize a gesture
+     * 
+     * @param gesture the query
+     * @return a list of predictions of possible entries for a given gesture
+     */
+    public ArrayList<Prediction> recognize(Gesture gesture) {
+        Instance instance = Instance.createInstance(this, gesture, null);
+        return mClassifier.classify(this, instance);
+    }
+
+    /**
+     * Add a gesture for the entry
+     * 
+     * @param entryName entry name
+     * @param gesture
+     */
+    public void addGesture(String entryName, Gesture gesture) {
+        if (Config.DEBUG) {
+            Log.v(LOGTAG, "Add an example for gesture: " + entryName);
+        }
+        if (entryName == null || entryName.length() == 0) {
+            return;
+        }
+        ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
+        if (gestures == null) {
+            gestures = new ArrayList<Gesture>();
+            mEntryName2gestures.put(entryName, gestures);
+        }
+        gestures.add(gesture);
+        mClassifier.addInstance(Instance.createInstance(this, gesture, entryName));
+        mChanged = true;
+    }
+
+    /**
+     * Remove a gesture from the library. If there are no more gestures for the
+     * given entry, the gesture entry will be removed.
+     * 
+     * @param entryName entry name
+     * @param gesture
+     */
+    public void removeGesture(String entryName, Gesture gesture) {
+        ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
+        if (gestures == null) {
+            return;
+        }
+
+        gestures.remove(gesture);
+
+        // if there are no more samples, remove the entry automatically
+        if (gestures.isEmpty()) {
+            mEntryName2gestures.remove(entryName);
+        }
+
+        mClassifier.removeInstance(gesture.getID());
+
+        mChanged = true;
+    }
+
+    /**
+     * Remove a entry of gestures
+     * 
+     * @param entryName the entry name
+     */
+    public void removeEntireEntry(String entryName) {
+        mEntryName2gestures.remove(entryName);
+        mClassifier.removeInstances(entryName);
+        mChanged = true;
+    }
+
+    /**
+     * Get all the gestures of an entry
+     * 
+     * @param entryName
+     * @return the list of gestures that is under this name
+     */
+    @SuppressWarnings("unchecked")
+    public ArrayList<Gesture> getGestures(String entryName) {
+        ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
+        if (gestures != null) {
+            return (ArrayList<Gesture>)gestures.clone();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Save the gesture library
+     */
+    public void save() {
+        if (!mChanged)
+            return;
+
+        try {
+            File file = new File(mGestureFileName);
+            if (!file.getParentFile().exists()) {
+                file.getParentFile().mkdirs();
+            }
+            if (Config.DEBUG) {
+                Log.v(LOGTAG, "Save to " + mGestureFileName);
+            }
+            BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(
+                    mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
+
+            PrintWriter writer = new PrintWriter(outputStream);
+            XmlSerializer serializer = Xml.newSerializer();
+            serializer.setOutput(writer);
+            serializer.startDocument(Encoding.ISO_8859_1.name(), null);
+            serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
+            HashMap<String, ArrayList<Gesture>> maps = mEntryName2gestures;
+            Iterator<String> it = maps.keySet().iterator();
+            while (it.hasNext()) {
+                String key = it.next();
+                ArrayList<Gesture> examples = maps.get(key);
+                // save an entry
+                serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
+                serializer.attribute(NAMESPACE, GestureConstants.XML_TAG_NAME, key);
+                int count = examples.size();
+                for (int i = 0; i < count; i++) {
+                    Gesture gesture = examples.get(i);
+                    // save each gesture in the entry
+                    gesture.toXML(NAMESPACE, serializer);
+                }
+                serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
+            }
+            serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
+            serializer.endDocument();
+            serializer.flush();
+            writer.close();
+            outputStream.close();
+            mChanged = false;
+        } catch (IOException ex) {
+            Log.d(LOGTAG, "Failed to save gestures:", ex);
+        }
+    }
+
+    /**
+     * Load the gesture library
+     */
+    public void load() {
+        File file = new File(mGestureFileName);
+        if (file.exists()) {
+            try {
+                if (Config.DEBUG) {
+                    Log.v(LOGTAG, "Load from " + mGestureFileName);
+                }
+                BufferedInputStream in = new BufferedInputStream(new FileInputStream(
+                        mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
+                Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler());
+                in.close();
+            } catch (SAXException ex) {
+                Log.d(LOGTAG, "Failed to load gestures:", ex);
+            } catch (IOException ex) {
+                Log.d(LOGTAG, "Failed to load gestures:", ex);
+            }
+        }
+    }
+
+    private class CompactInkHandler implements ContentHandler {
+        Gesture currentGesture = null;
+
+        StringBuilder buffer = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
+
+        String entryName;
+
+        ArrayList<Gesture> gestures;
+
+        CompactInkHandler() {
+        }
+
+        public void characters(char[] ch, int start, int length) {
+            buffer.append(ch, start, length);
+        }
+
+        public void endDocument() {
+        }
+
+        public void endElement(String uri, String localName, String qName) {
+            if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
+                mEntryName2gestures.put(entryName, gestures);
+                gestures = null;
+            } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
+                gestures.add(currentGesture);
+                mClassifier.addInstance(Instance.createInstance(GestureLibrary.this,
+                        currentGesture, entryName));
+                currentGesture = null;
+            } else if (localName.equals(GestureConstants.XML_TAG_STROKE)) {
+                currentGesture.addStroke(GestureStroke.createFromString(buffer.toString()));
+                buffer.setLength(0);
+            }
+        }
+
+        public void endPrefixMapping(String prefix) {
+        }
+
+        public void ignorableWhitespace(char[] ch, int start, int length) {
+        }
+
+        public void processingInstruction(String target, String data) {
+        }
+
+        public void setDocumentLocator(Locator locator) {
+        }
+
+        public void skippedEntity(String name) {
+        }
+
+        public void startDocument() {
+        }
+
+        public void startElement(String uri, String localName, String qName, Attributes attributes) {
+            if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
+                gestures = new ArrayList<Gesture>();
+                entryName = attributes.getValue(NAMESPACE, GestureConstants.XML_TAG_NAME);
+            } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
+                currentGesture = new Gesture();
+                currentGesture.setID(Long.parseLong(attributes.getValue(NAMESPACE,
+                        GestureConstants.XML_TAG_ID)));
+            }
+        }
+
+        public void startPrefixMapping(String prefix, String uri) {
+        }
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/tests/sketch/src/com/android/gesture/GestureListener.java
index ebb4149..9b50714 100755
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ b/tests/sketch/src/com/android/gesture/GestureListener.java
@@ -18,8 +18,13 @@
 
 import android.view.MotionEvent;
 
+/**
+ * An interface for processing gesture events
+ */
 public interface GestureListener {
-    public void onStartGesture(GesturePad pad, MotionEvent event);
-    public void onGesture(GesturePad pad, MotionEvent event);
-    public void onFinishGesture(GesturePad pad, MotionEvent event);
+    public void onStartGesture(GestureOverlay overlay, MotionEvent event);
+
+    public void onGesture(GestureOverlay overlay, MotionEvent event);
+
+    public void onFinishGesture(GestureOverlay overlay, MotionEvent event);
 }
diff --git a/tests/sketch/src/com/android/gesture/GestureOverlay.java b/tests/sketch/src/com/android/gesture/GestureOverlay.java
new file mode 100755
index 0000000..9907831
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureOverlay.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gesture;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * A (transparent) overlay for gesture input that can be placed on top of other
+ * widgets. The view can also be opaque.
+ */
+
+public class GestureOverlay extends View {
+
+    static final float TOUCH_TOLERANCE = 3;
+
+    private static final int TRANSPARENT_BACKGROUND = Color.argb(0, 0, 0, 0);
+
+    private static final float FADING_ALPHA_CHANGE = 0.03f;
+
+    private static final long FADING_REFRESHING_RATE = 100;
+
+    private static final int GESTURE_STROKE_WIDTH = 12;
+
+    private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
+
+    private static final BlurMaskFilter BLUR_MASK_FILTER = new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL);
+    
+    private static final boolean DITHER_FLAG = true;
+
+    private static final int REFRESH_RANGE = 10;
+
+    public static final int DEFAULT_GESTURE_COLOR = Color.argb(255, 255, 255, 0);
+
+    // double buffering
+    private Paint mGesturePaint;
+
+    private Bitmap mBitmap; // with transparent background
+
+    private Canvas mBitmapCanvas;
+
+    // for rendering immediate ink feedback
+    private Rect mInvalidRect = new Rect();
+
+    private Path mPath;
+
+    private float mX;
+
+    private float mY;
+    
+    private float mCurveEndX;
+    
+    private float mCurveEndY;
+
+    // current gesture
+    private Gesture mCurrentGesture = null;
+
+    // gesture event handlers
+    ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>();
+
+    private ArrayList<GesturePoint> mPointBuffer = null;
+
+    // fading out effect
+    private boolean mIsFadingOut = false;
+
+    private float mFadingAlpha = 1;
+
+    private Handler mHandler = new Handler();
+
+    private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
+
+    private Runnable mFadingOut = new Runnable() {
+        public void run() {
+            if (mIsFadingOut) {
+                mFadingAlpha -= FADING_ALPHA_CHANGE;
+                if (mFadingAlpha <= 0) {
+                    mIsFadingOut = false;
+                    mPath = null;
+                    mCurrentGesture = null;
+                    mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+                } else {
+                    mHandler.postDelayed(this, FADING_REFRESHING_RATE);
+                }
+                invalidate();
+            }
+        }
+    };
+
+    public GestureOverlay(Context context) {
+        super(context);
+        init();
+    }
+
+    public GestureOverlay(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public ArrayList<GesturePoint> getCurrentStroke() {
+        return mPointBuffer;
+    }
+
+    public Gesture getCurrentGesture() {
+        return mCurrentGesture;
+    }
+
+    /**
+     * Set Gesture color
+     * 
+     * @param color
+     */
+    public void setGestureColor(int color) {
+        mGesturePaint.setColor(color);
+        if (mCurrentGesture != null) {
+            mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+            mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
+        }
+    }
+
+    /**
+     * Set the gesture to be shown in the view
+     * 
+     * @param gesture
+     */
+    public void setCurrentGesture(Gesture gesture) {
+        if (mCurrentGesture != null) {
+            clear(false);
+        }
+
+        mCurrentGesture = gesture;
+
+        if (gesture != null) {
+            if (mBitmapCanvas != null) {
+                gesture.draw(mBitmapCanvas, mGesturePaint);
+                invalidate();
+            }
+        }
+    }
+
+    private void init() {
+        mGesturePaint = new Paint();
+        mGesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
+        mGesturePaint.setColor(DEFAULT_GESTURE_COLOR);
+        mGesturePaint.setStyle(Paint.Style.STROKE);
+        mGesturePaint.setStrokeJoin(Paint.Join.ROUND);
+        mGesturePaint.setStrokeCap(Paint.Cap.ROUND);
+        mGesturePaint.setStrokeWidth(GESTURE_STROKE_WIDTH);
+        mGesturePaint.setDither(DITHER_FLAG);
+
+        mPath = null;
+    }
+
+    @Override
+    protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
+        super.onSizeChanged(width, height, oldWidth, oldHeight);
+        if (width <= 0 || height <= 0) {
+            return;
+        }
+        int targetWidth = width > oldWidth ? width : oldWidth;
+        int targetHeight = height > oldHeight ? height : oldHeight;
+        mBitmap = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
+        mBitmapCanvas = new Canvas(mBitmap);
+        mBitmapCanvas.drawColor(TRANSPARENT_BACKGROUND);
+        if (mCurrentGesture != null) {
+            mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
+        }
+    }
+
+    public void addGestureListener(GestureListener listener) {
+        mGestureListeners.add(listener);
+    }
+
+    public void removeGestureListener(GestureListener listener) {
+        mGestureListeners.remove(listener);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        // draw double buffer
+        if (mIsFadingOut) {
+            mBitmapPaint.setAlpha((int) (255 * mFadingAlpha));
+            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+        } else {
+            mBitmapPaint.setAlpha(255);
+            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
+        }
+
+        // draw the current stroke
+        if (mPath != null) {
+            canvas.drawPath(mPath, mGesturePaint);
+        }
+    }
+
+    /**
+     * Clear up the overlay
+     * 
+     * @param fadeOut whether the gesture on the overlay should fade out
+     *            gradually or disappear immediately
+     */
+    public void clear(boolean fadeOut) {
+        if (fadeOut) {
+            mFadingAlpha = 1;
+            mIsFadingOut = true;
+            mHandler.removeCallbacks(mFadingOut);
+            mHandler.postDelayed(mFadingOut, FADING_REFRESHING_RATE);
+        } else {
+            mPath = null;
+            mCurrentGesture = null;
+            if (mBitmap != null) {
+                mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+                invalidate();
+            }
+        }
+    }
+
+    public void cancelFadingOut() {
+        mIsFadingOut = false;
+        mHandler.removeCallbacks(mFadingOut);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+
+        if (!isEnabled()) {
+            return true;
+        }
+
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                Rect rect = touchStart(event);
+                invalidate(rect);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                rect = touchMove(event);
+                if (rect != null) {
+                    invalidate(rect);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                touchUp(event);
+                invalidate();
+                break;
+        }
+
+        return true;
+    }
+
+    private Rect touchStart(MotionEvent event) {
+        // pass the event to handlers
+        ArrayList<GestureListener> listeners = mGestureListeners;
+        int count = listeners.size();
+        for (int i = 0; i < count; i++) {
+            GestureListener listener = listeners.get(i);
+            listener.onStartGesture(this, event);
+        }
+
+        // if there is fading out going on, stop it.
+        if (mIsFadingOut) {
+            mIsFadingOut = false;
+            mHandler.removeCallbacks(mFadingOut);
+            mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
+            mCurrentGesture = null;
+        }
+
+        float x = event.getX();
+        float y = event.getY();
+
+        mX = x;
+        mY = y;
+
+        if (mCurrentGesture == null) {
+            mCurrentGesture = new Gesture();
+        }
+
+        mPointBuffer = new ArrayList<GesturePoint>();
+        mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+
+        mPath = new Path();
+        mPath.moveTo(x, y);
+
+        mInvalidRect.set((int) x - REFRESH_RANGE, (int) y - REFRESH_RANGE, (int) x + REFRESH_RANGE,
+                (int) y + REFRESH_RANGE);
+        
+        mCurveEndX = x;
+        mCurveEndY = y;
+        
+        return mInvalidRect;
+    }
+
+    private Rect touchMove(MotionEvent event) {
+        Rect areaToRefresh = null;
+        
+        float x = event.getX();
+        float y = event.getY();
+
+        float dx = Math.abs(x - mX);
+        float dy = Math.abs(y - mY);
+        
+        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
+            
+            // start with the curve end
+            mInvalidRect.set((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
+                    (int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
+            
+            mCurveEndX  = (x + mX) / 2;
+            mCurveEndY = (y + mY) / 2;
+            mPath.quadTo(mX, mY, mCurveEndX, mCurveEndY);
+            
+            // union with the control point of the new curve
+            mInvalidRect.union((int) mX - REFRESH_RANGE, (int) mY - REFRESH_RANGE,
+                    (int) mX + REFRESH_RANGE, (int) mY + REFRESH_RANGE);
+            
+            // union with the end point of the new curve
+            mInvalidRect.union((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
+                    (int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
+
+            areaToRefresh = mInvalidRect;
+            
+            mX = x;
+            mY = y;
+        }
+        
+
+        mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+
+        // pass the event to handlers
+        ArrayList<GestureListener> listeners = mGestureListeners;
+        int count = listeners.size();
+        for (int i = 0; i < count; i++) {
+            GestureListener listener = listeners.get(i);
+            listener.onGesture(this, event);
+        }
+        
+        return areaToRefresh;
+    }
+
+    private void touchUp(MotionEvent event) {
+        // add the stroke to the current gesture
+        mCurrentGesture.addStroke(new GestureStroke(mPointBuffer));
+
+        // add the stroke to the double buffer
+        mGesturePaint.setMaskFilter(BLUR_MASK_FILTER);
+        mBitmapCanvas.drawPath(mPath, mGesturePaint);
+        mGesturePaint.setMaskFilter(null);
+        
+        // pass the event to handlers
+        ArrayList<GestureListener> listeners = mGestureListeners;
+        int count = listeners.size();
+        for (int i = 0; i < count; i++) {
+            GestureListener listener = listeners.get(i);
+            listener.onFinishGesture(this, event);
+        }
+        
+        mPath = null;        
+        mPointBuffer = null;
+    }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/GesturePad.java b/tests/sketch/src/com/android/gesture/GesturePad.java
deleted file mode 100755
index 45a09e6..0000000
--- a/tests/sketch/src/com/android/gesture/GesturePad.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.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/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/GesturePoint.java
old mode 100755
new mode 100644
similarity index 60%
copy from tests/sketch/src/com/android/gesture/recognizer/Prediction.java
copy to tests/sketch/src/com/android/gesture/GesturePoint.java
index c318754..d06eff47
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ b/tests/sketch/src/com/android/gesture/GesturePoint.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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,23 +14,22 @@
  * limitations under the License.
  */
 
-package com.android.gesture.recognizer;
+package com.android.gesture;
 
 /**
- * 
- * A recognition result that includes the label and its score
+ * A timed point of a gesture stroke
  */
-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;
-	}
+
+public class GesturePoint {
+    public final float xpos;
+
+    public final float ypos;
+
+    public final long timestamp;
+
+    public GesturePoint(float x, float y, long t) {
+        xpos = x;
+        ypos = y;
+        timestamp = t;
+    }
 }
diff --git a/tests/sketch/src/com/android/gesture/GestureStroke.java b/tests/sketch/src/com/android/gesture/GestureStroke.java
new file mode 100644
index 0000000..b5e38b7
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureStroke.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gesture;
+
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * A gesture stroke started on a touch down and ended on a touch up.
+ */
+public class GestureStroke {
+    public final RectF boundingBox;
+
+    public final float length;
+
+    public final float[] points;
+
+    private final long[] timestamps;
+
+    private Path mCachedPath;
+
+    /**
+     * Construct a gesture stroke from a list of gesture points
+     * 
+     * @param pts
+     */
+    public GestureStroke(ArrayList<GesturePoint> pts) {
+        float[] tmpPoints = new float[pts.size() * 2];
+        long[] times = new long[pts.size()];
+
+        RectF bx = null;
+        float len = 0;
+        int index = 0;
+        int count = pts.size();
+
+        for (int i = 0; i < count; i++) {
+            GesturePoint p = pts.get(i);
+            tmpPoints[i * 2] = p.xpos;
+            tmpPoints[i * 2 + 1] = p.ypos;
+            times[index] = p.timestamp;
+
+            if (bx == null) {
+                bx = new RectF();
+                bx.top = p.ypos;
+                bx.left = p.xpos;
+                bx.right = p.xpos;
+                bx.bottom = p.ypos;
+                len = 0;
+            } else {
+                len += Math.sqrt(Math.pow(p.xpos - tmpPoints[(i - 1) * 2], 2)
+                        + Math.pow(p.ypos - tmpPoints[(i -1 ) * 2 + 1], 2));
+                bx.union(p.xpos, p.ypos);
+            }
+            index++;
+        }
+        
+        timestamps = times;
+        points = tmpPoints;
+        boundingBox = bx;
+        length = len;
+    }
+
+    /**
+     * Draw the gesture with a given canvas and paint
+     * 
+     * @param canvas
+     */
+    void draw(Canvas canvas, Paint paint) {
+        if (mCachedPath == null) {
+            float[] pts = points;
+            int count = pts.length;
+            Path path = null;
+            float mX = 0, mY = 0;
+            for (int i = 0; i < count; i += 2) {
+                float x = pts[i];
+                float y = pts[i + 1];
+                if (path == null) {
+                    path = new Path();
+                    path.moveTo(x, y);
+                    mX = x;
+                    mY = y;
+                } else {
+                    float dx = Math.abs(x - mX);
+                    float dy = Math.abs(y - mY);
+                    if (dx >= 3 || dy >= 3) {
+                        path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+                        mX = x;
+                        mY = y;
+                    }
+                }
+            }
+
+            mCachedPath = path;
+        }
+
+        canvas.drawPath(mCachedPath, paint);
+    }
+
+    /**
+     * Convert the stroke to a Path based on the number of points
+     * 
+     * @param width the width of the bounding box of the target path
+     * @param height the height of the bounding box of the target path
+     * @param numSample the number of points needed
+     * @return the path
+     */
+    public Path toPath(float width, float height, int numSample) {
+        float[] pts = GestureUtils.temporalSampling(this, numSample);
+        RectF rect = boundingBox;
+        float scale = height / rect.height();
+        Matrix matrix = new Matrix();
+        matrix.setTranslate(-rect.left, -rect.top);
+        Matrix scaleMatrix = new Matrix();
+        scaleMatrix.setScale(scale, scale);
+        matrix.postConcat(scaleMatrix);
+        Matrix translate = new Matrix();
+        matrix.postConcat(translate);
+        matrix.mapPoints(pts);
+
+        Path path = null;
+        float mX = 0;
+        float mY = 0;
+        int count = pts.length;
+        for (int i = 0; i < count; i += 2) {
+            float x = pts[i];
+            float y = pts[i + 1];
+            if (path == null) {
+                path = new Path();
+                path.moveTo(x, y);
+                mX = x;
+                mY = y;
+            } else {
+                float dx = Math.abs(x - mX);
+                float dy = Math.abs(y - mY);
+                if (dx >= GestureOverlay.TOUCH_TOLERANCE || dy >= GestureOverlay.TOUCH_TOLERANCE) {
+                    path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+                    mX = x;
+                    mY = y;
+                }
+            }
+        }
+        return path;
+    }
+
+    /**
+     * Save the gesture stroke as XML
+     * 
+     * @param namespace
+     * @param serializer
+     * @throws IOException
+     */
+    void toXML(String namespace, XmlSerializer serializer) throws IOException {
+        serializer.startTag(namespace, GestureConstants.XML_TAG_STROKE);
+        serializer.text(toString());
+        serializer.endTag(namespace, GestureConstants.XML_TAG_STROKE);
+    }
+
+    /**
+     * Create a gesture stroke from a string
+     * 
+     * @param str
+     * @return the gesture stroke
+     */
+    public static GestureStroke createFromString(String str) {
+        ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(
+                GestureConstants.STROKE_POINT_BUFFER_SIZE);
+        int endIndex;
+        int startIndex = 0;
+        while ((endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1)) != -1) {
+
+            // parse x
+            String token = str.substring(startIndex, endIndex);
+            float x = Float.parseFloat(token);
+            startIndex = endIndex + 1;
+
+            // parse y
+            endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
+            token = str.substring(startIndex, endIndex);
+            float y = Float.parseFloat(token);
+            startIndex = endIndex + 1;
+
+            // parse t
+            endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
+            token = str.substring(startIndex, endIndex);
+            long time = Long.parseLong(token);
+            startIndex = endIndex + 1;
+
+            points.add(new GesturePoint(x, y, time));
+        }
+        return new GestureStroke(points);
+    }
+
+    /**
+     * Convert the stroke to string
+     */
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
+        float[] pts = points;
+        long[] times = timestamps;
+        int count = points.length;
+        for (int i = 0; i < count; i += 2) {
+            str.append(points[i] + GestureConstants.STRING_STROKE_DELIIMITER + points[i + 1]
+                    + GestureConstants.STRING_STROKE_DELIIMITER + times[i / 2]
+                    + GestureConstants.STRING_STROKE_DELIIMITER);
+        }
+        return str.toString();
+    }
+
+    /**
+     * Invalidate the cached path that is used for rendering the stroke
+     */
+    public void invalidate() {
+        mCachedPath = null;
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureUtils.java b/tests/sketch/src/com/android/gesture/GestureUtils.java
new file mode 100755
index 0000000..09d2625
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/GestureUtils.java
@@ -0,0 +1,426 @@
+/*
+ * 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.RectF;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class GestureUtils {
+
+    private static final int TEMPORAL_SAMPLING_RATE = 16;
+   
+    protected static float[] spatialSampling(Gesture gesture, int sampleMatrixDimension) {
+        final float targetPatchSize = sampleMatrixDimension - 1; // edge inclusive
+        float[] sample = new float[sampleMatrixDimension * sampleMatrixDimension];
+        Arrays.fill(sample, 0);
+
+        RectF rect = gesture.getBoundingBox();
+        float sx = targetPatchSize / rect.width();
+        float sy = targetPatchSize / rect.height();
+        float scale = sx < sy ? sx : sy;
+        android.graphics.Matrix trans = new android.graphics.Matrix();
+        trans.setScale(scale, scale);
+        android.graphics.Matrix translate1 = new android.graphics.Matrix();
+        translate1.setTranslate(-rect.centerX(), -rect.centerY());
+        trans.preConcat(translate1);
+        android.graphics.Matrix translate2 = new android.graphics.Matrix();
+        translate2.setTranslate(targetPatchSize / 2, targetPatchSize / 2);
+        trans.postConcat(translate2);
+
+        ArrayList<GestureStroke> strokes = gesture.getStrokes();
+        int count = strokes.size();
+        int size;
+        float xpos;
+        float ypos;
+        for (int index = 0; index < count; index++) {
+            GestureStroke stroke = strokes.get(index);
+            size = stroke.points.length;
+            float[] pts = new float[size];
+            trans.mapPoints(pts, 0, stroke.points, 0, size / 2);
+            float segmentEndX = -1;
+            float segmentEndY = -1;
+            
+            for (int i = 0; i < size; i += 2) {
+                
+                float segmentStartX = pts[i] < 0 ? 0 : pts[i];
+                float segmentStartY = pts[i + 1] < 0 ? 0 : pts[i + 1];
+                
+                if (segmentStartX > targetPatchSize) {
+                    segmentStartX = targetPatchSize;
+                } 
+                
+                if (segmentStartY > targetPatchSize) {
+                    segmentStartY = targetPatchSize;
+                }
+                 
+                plot(segmentStartX, segmentStartY, sample, sampleMatrixDimension);
+                
+                if (segmentEndX != -1) {
+                    // evaluate horizontally
+                    if (segmentEndX > segmentStartX) {
+                        xpos = (float) Math.ceil(segmentStartX);
+                        float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX);
+                        while (xpos < segmentEndX) {
+                            ypos = slope * (xpos - segmentStartX) + segmentStartY;
+                            plot(xpos, ypos, sample, sampleMatrixDimension); 
+                            xpos++;
+                        }
+                    } else if (segmentEndX < segmentStartX){
+                        xpos = (float) Math.ceil(segmentEndX);
+                        float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX);
+                        while (xpos < segmentStartX) {
+                            ypos = slope * (xpos - segmentStartX) + segmentStartY;
+                            plot(xpos, ypos, sample, sampleMatrixDimension); 
+                            xpos++;
+                        }
+                    }
+
+                    // evaluating vertically
+                    if (segmentEndY > segmentStartY) {
+                        ypos = (float) Math.ceil(segmentStartY);
+                        float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY);
+                        while (ypos < segmentEndY) {
+                            xpos = invertSlope * (ypos - segmentStartY) + segmentStartX;
+                            plot(xpos, ypos, sample, sampleMatrixDimension); 
+                            ypos++;
+                        }
+                    } else if (segmentEndY < segmentStartY) {
+                        ypos = (float) Math.ceil(segmentEndY);
+                        float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY);
+                        while (ypos < segmentStartY) {
+                            xpos = invertSlope * (ypos - segmentStartY) + segmentStartX; 
+                            plot(xpos, ypos, sample, sampleMatrixDimension); 
+                            ypos++;
+                        }
+                    }
+                } 
+                
+                segmentEndX = segmentStartX;
+                segmentEndY = segmentStartY;
+            }
+        }
+
+
+        return sample;
+    }
+
+    
+    private static void plot(float x, float y, float[] sample, int sampleSize) {
+        x = x < 0 ? 0 : x;
+        y = y < 0 ? 0 : y;
+        int xFloor = (int) Math.floor(x);
+        int xCeiling = (int) Math.ceil(x);
+        int yFloor = (int) Math.floor(y);
+        int yCeiling = (int) Math.ceil(y);
+        
+        // if it's an integer
+        if (x == xFloor && y == yFloor) {
+            int index = yCeiling * sampleSize + xCeiling;
+            if (sample[index] < 1){
+                sample[index] = 1;
+            }
+        } else {
+            double topLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yFloor - y, 2));
+            double topRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yFloor - y, 2));
+            double btmLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yCeiling - y, 2));
+            double btmRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yCeiling - y, 2));
+            double sum = topLeft + topRight + btmLeft + btmRight;
+            
+            double value = topLeft / sum;
+            int index = yFloor * sampleSize + xFloor;
+            if (value > sample[index]){
+                sample[index] = (float) value;
+            }
+            
+            value = topRight / sum;
+            index = yFloor * sampleSize + xCeiling;
+            if (value > sample[index]){
+                sample[index] = (float) value;
+            }
+            
+            value = btmLeft / sum;
+            index = yCeiling * sampleSize + xFloor;
+            if (value > sample[index]){
+                sample[index] = (float) value;
+            }
+            
+            value = btmRight / sum;
+            index = yCeiling * sampleSize + xCeiling;
+            if (value > sample[index]){
+                sample[index] = (float) value;
+            }
+        }
+    }
+    
+    /**
+     * Featurize a stroke into a vector of a given number of elements
+     * 
+     * @param stroke
+     * @param sampleSize
+     * @return a float array
+     */
+    protected static float[] temporalSampling(GestureStroke stroke, int sampleSize) {
+        final float increment = stroke.length / (sampleSize - 1);
+        int vectorLength = sampleSize * 2;
+        float[] vector = new float[vectorLength];
+        float distanceSoFar = 0;
+        float[] pts = stroke.points;
+        float lstPointX = pts[0];
+        float lstPointY = pts[1];
+        int index = 0;
+        float currentPointX = Float.MIN_VALUE;
+        float currentPointY = Float.MIN_VALUE;
+        vector[index] = lstPointX;
+        index++;
+        vector[index] = lstPointY;
+        index++;
+        int i = 0;
+        int count = pts.length / 2;
+        while (i < count) {
+            if (currentPointX == Float.MIN_VALUE) {
+                i++;
+                if (i >= count) {
+                    break;
+                }
+                currentPointX = pts[i * 2];
+                currentPointY = pts[i * 2 + 1];
+            }
+            float deltaX = currentPointX - lstPointX;
+            float deltaY = currentPointY - lstPointY;
+            float distance = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+            if (distanceSoFar + distance >= increment) {
+                float ratio = (increment - distanceSoFar) / distance;
+                float nx = lstPointX + ratio * deltaX;
+                float ny = lstPointY + ratio * deltaY;
+                vector[index] = nx;
+                index++;
+                vector[index] = ny;
+                index++;
+                lstPointX = nx;
+                lstPointY = ny;
+                distanceSoFar = 0;
+            } else {
+                lstPointX = currentPointX;
+                lstPointY = currentPointY;
+                currentPointX = Float.MIN_VALUE;
+                currentPointY = Float.MIN_VALUE;
+                distanceSoFar += distance;
+            }
+        }
+
+        for (i = index; i < vectorLength; i += 2) {
+            vector[i] = lstPointX;
+            vector[i + 1] = lstPointY;
+        }
+        return vector;
+    }
+
+    /**
+     * Calculate the centroid 
+     * 
+     * @param points
+     * @return the centroid
+     */
+    public static float[] computeCentroid(float[] points) {
+        float centerX = 0;
+        float centerY = 0;
+        int count = points.length;
+        for (int i = 0; i < count; i++) {
+            centerX += points[i];
+            i++;
+            centerY += points[i];
+        }
+        float[] center = new float[2];
+        center[0] = 2 * centerX / count;
+        center[1] = 2 * centerY / count;
+
+        return center;
+    }
+
+    /**
+     * calculate the variance-covariance matrix, treat each point as a sample
+     * 
+     * @param points
+     * @return the covariance matrix
+     */
+    private 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;
+        int count = points.length;
+        for (int i = 0; i < count; 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] /= (count / 2);
+        array[0][1] /= (count / 2);
+        array[1][0] /= (count / 2);
+        array[1][1] /= (count / 2);
+
+        return array;
+    }
+
+    public static float computeTotalLength(float[] points) {
+        float sum = 0;
+        int count = points.length - 4;
+        for (int i = 0; i < count; 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;
+    }
+
+    /**
+     * Calculate the squared Euclidean distance between two vectors
+     * 
+     * @param vector1
+     * @param vector2
+     * @return the distance
+     */
+    protected static double squaredEuclideanDistance(float[] vector1, float[] vector2) {
+        double squaredDistance = 0;
+        int size = vector1.length;
+        for (int i = 0; i < size; i++) {
+            float difference = vector1[i] - vector2[i];
+            squaredDistance += difference * difference;
+        }
+        return squaredDistance / size;
+    }
+
+    /**
+     * Calculate the cosine distance between two instances
+     * 
+     * @param in1
+     * @param in2
+     * @return the distance between 0 and Math.PI
+     */
+    protected static double cosineDistance(Instance in1, Instance in2) {
+        float sum = 0;
+        float[] vector1 = in1.vector;
+        float[] vector2 = in2.vector;
+        int len = vector1.length;
+        for (int i = 0; i < len; i++) {
+            sum += vector1[i] * vector2[i];
+        }
+        return Math.acos(sum / (in1.magnitude * in2.magnitude));
+    }
+
+    public static OrientedBoundingBox computeOrientedBBX(ArrayList<GesturePoint> pts) {
+        GestureStroke stroke = new GestureStroke(pts);
+        float[] points = temporalSampling(stroke, TEMPORAL_SAMPLING_RATE);
+        return computeOrientedBBX(points);
+    }
+
+    public static OrientedBoundingBox computeOrientedBBX(float[] points) {
+        float[] meanVector = computeCentroid(points);
+        return computeOrientedBBX(points, meanVector);
+    }
+
+    public static OrientedBoundingBox computeOrientedBBX(float[] points, float[] centroid) {
+
+        android.graphics.Matrix tr = new android.graphics.Matrix();
+        tr.setTranslate(-centroid[0], -centroid[1]);
+        tr.mapPoints(points);
+
+        double[][] array = computeCoVariance(points);
+        double[] targetVector = computeOrientation(array);
+
+        float angle;
+        if (targetVector[0] == 0 && targetVector[1] == 0) {
+            angle = -90;
+        } else { // -PI<alpha<PI
+            angle = (float) Math.atan2(targetVector[1], targetVector[0]);
+            angle = (float) (180 * angle / Math.PI);
+            android.graphics.Matrix trans = new android.graphics.Matrix();
+            trans.setRotate(-angle);
+            trans.mapPoints(points);
+        }
+
+        float minx = Float.MAX_VALUE;
+        float miny = Float.MAX_VALUE;
+        float maxx = Float.MIN_VALUE;
+        float maxy = Float.MIN_VALUE;
+        int count = points.length;
+        for (int i = 0; i < count; i++) {
+            if (points[i] < minx) {
+                minx = points[i];
+            }
+            if (points[i] > maxx) {
+                maxx = points[i];
+            }
+            i++;
+            if (points[i] < miny) {
+                miny = points[i];
+            }
+            if (points[i] > maxy) {
+                maxy = points[i];
+            }
+        }
+
+        OrientedBoundingBox bbx = new OrientedBoundingBox(angle, centroid[0], centroid[1], maxx
+                - minx, maxy - miny);
+        return bbx;
+    }
+
+    private static double[] computeOrientation(double[][] covarianceMatrix) {
+        double[] targetVector = new double[2];
+        if (covarianceMatrix[0][1] == 0 || covarianceMatrix[1][0] == 0) {
+            targetVector[0] = 1;
+            targetVector[1] = 0;
+        }
+
+        double a = -covarianceMatrix[0][0] - covarianceMatrix[1][1];
+        double b = covarianceMatrix[0][0] * covarianceMatrix[1][1] - covarianceMatrix[0][1]
+                * covarianceMatrix[1][0];
+        double value = a / 2;
+        double rightside = Math.sqrt(Math.pow(value, 2) - b);
+        double lambda1 = -value + rightside;
+        double lambda2 = -value - rightside;
+        if (lambda1 == lambda2) {
+            targetVector[0] = 0;
+            targetVector[1] = 0;
+        } else {
+            double lambda = lambda1 > lambda2 ? lambda1 : lambda2;
+            targetVector[0] = 1;
+            targetVector[1] = (lambda - covarianceMatrix[0][0]) / covarianceMatrix[0][1];
+        }
+        return targetVector;
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/Instance.java b/tests/sketch/src/com/android/gesture/Instance.java
new file mode 100755
index 0000000..4fbebf9
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/Instance.java
@@ -0,0 +1,106 @@
+/*
+ * 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;
+
+/**
+ * An instance represents a sample if the label is available or a query if the
+ * label is null.
+ */
+class Instance {
+
+    private static final int SEQUENCE_SAMPLE_SIZE = 16;
+
+    private static final int PATCH_SAMPLE_SIZE = 8;
+
+    private final static float[] ORIENTATIONS = {
+            0, 45, 90, 135, 180, -0, -45, -90, -135, -180
+    };
+
+    // the feature vector
+    final float[] vector;
+
+    // the label can be null
+    final String label;
+
+    // the length of the vector
+    final float magnitude;
+
+    // the id of the instance
+    final long instanceID;
+
+    private Instance(long id, float[] sample, String sampleName) {
+        instanceID = id;
+        vector = sample;
+        label = sampleName;
+        float sum = 0;
+        int size = sample.length;
+        for (int i = 0; i < size; i++) {
+            sum += sample[i] * sample[i];
+        }
+        magnitude = (float) Math.sqrt(sum);
+    }
+
+    /**
+     * create a learning instance for a single stroke gesture
+     * 
+     * @param gesture
+     * @param label
+     * @return the instance
+     */
+    static Instance createInstance(GestureLibrary gesturelib, Gesture gesture, String label) {
+        float[] pts;
+        if (gesturelib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
+            pts = temporalSampler(gesturelib, gesture);
+        } else {
+            pts = spatialSampler(gesture);
+        }
+        return new Instance(gesture.getID(), pts, label);
+    }
+
+    private static float[] spatialSampler(Gesture gesture) {
+        float[] pts = GestureUtils.spatialSampling(gesture, PATCH_SAMPLE_SIZE);
+        return pts;
+    }
+
+    private static float[] temporalSampler(GestureLibrary gesturelib, Gesture gesture) {
+        float[] pts = GestureUtils.temporalSampling(gesture.getStrokes().get(0),
+                SEQUENCE_SAMPLE_SIZE);
+        float[] center = GestureUtils.computeCentroid(pts);
+        float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]);
+        orientation *= 180 / Math.PI;
+
+        float adjustment = -orientation;
+        if (gesturelib.getOrientationStyle() == GestureLibrary.ORIENTATION_SENSITIVE) {
+            int count = ORIENTATIONS.length;
+            for (int i = 0; i < count; i++) {
+                float delta = ORIENTATIONS[i] - orientation;
+                if (Math.abs(delta) < Math.abs(adjustment)) {
+                    adjustment = delta;
+                }
+            }
+        }
+
+        android.graphics.Matrix m = new android.graphics.Matrix();
+        m.setTranslate(-center[0], -center[1]);
+        android.graphics.Matrix rotation = new android.graphics.Matrix();
+        rotation.setRotate(adjustment);
+        m.postConcat(rotation);
+        m.mapPoints(pts);
+        return pts;
+    }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/InstanceLearner.java b/tests/sketch/src/com/android/gesture/InstanceLearner.java
new file mode 100644
index 0000000..95241d4
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/InstanceLearner.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gesture;
+
+import android.util.Config;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+/**
+ * An implementation of an instance-based learner
+ */
+
+class InstanceLearner extends Learner {
+
+    private static final String LOGTAG = "InstanceLearner";
+
+    @Override
+    ArrayList<Prediction> classify(GestureLibrary lib, Instance instance) {
+        ArrayList<Prediction> predictions = new ArrayList<Prediction>();
+        ArrayList<Instance> instances = getInstances();
+        int count = instances.size();
+        TreeMap<String, Double> label2score = new TreeMap<String, Double>();
+        for (int i = 0; i < count; i++) {
+            Instance sample = instances.get(i);
+            if (sample.vector.length != instance.vector.length) {
+                continue;
+            }
+            double distance;
+            if (lib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
+                distance = GestureUtils.cosineDistance(sample, instance);
+            } else {
+                distance = GestureUtils.squaredEuclideanDistance(sample.vector, instance.vector);
+            }
+            double weight;
+            if (distance == 0) {
+                weight = Double.MAX_VALUE;
+            } else {
+                weight = 1 / distance;
+            }
+            Double score = label2score.get(sample.label);
+            if (score == null || weight > score) {
+                label2score.put(sample.label, weight);
+            }
+        }
+
+        double sum = 0;
+        Iterator<String> lableIterator = label2score.keySet().iterator();
+        while (lableIterator.hasNext()) {
+            String name = lableIterator.next();
+            double score = label2score.get(name);
+            sum += score;
+            predictions.add(new Prediction(name, score));
+        }
+
+        // normalize
+        Iterator<Prediction> predictionIterator = predictions.iterator();
+        while (predictionIterator.hasNext()) {
+            Prediction name = predictionIterator.next();
+            name.score /= sum;
+        }
+
+        Collections.sort(predictions, new Comparator<Prediction>() {
+            public int compare(Prediction object1, Prediction object2) {
+                double score1 = object1.score;
+                double score2 = object2.score;
+                if (score1 > score2) {
+                    return -1;
+                } else if (score1 < score2) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+
+        if (Config.DEBUG) {
+            predictionIterator = predictions.iterator();
+            while (predictionIterator.hasNext()) {
+                Prediction name = predictionIterator.next();
+                Log.v(LOGTAG, "prediction [" + name.name + " = " + name.score + "]");
+            }
+        }
+
+        return predictions;
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/Learner.java b/tests/sketch/src/com/android/gesture/Learner.java
new file mode 100755
index 0000000..63f3156
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/Learner.java
@@ -0,0 +1,82 @@
+/*
+ * 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 java.util.ArrayList;
+
+/**
+ * The abstract class of a gesture learner
+ */
+abstract class Learner {
+
+    private final ArrayList<Instance> mInstances = new ArrayList<Instance>();
+
+    /**
+     * Add an instance to the learner
+     * 
+     * @param instance
+     */
+    void addInstance(Instance instance) {
+        mInstances.add(instance);
+    }
+
+    /**
+     * Retrieve all the instances
+     * 
+     * @return instances
+     */
+    ArrayList<Instance> getInstances() {
+        return mInstances;
+    }
+
+    /**
+     * Remove an instance based on its id
+     * 
+     * @param id
+     */
+    void removeInstance(long id) {
+        ArrayList<Instance> instances = mInstances;
+        int count = instances.size();
+        for (int i = 0; i < count; i++) {
+            Instance instance = instances.get(i);
+            if (id == instance.instanceID) {
+                instances.remove(instance);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Remove all the instances of a category
+     * 
+     * @param name the category name
+     */
+    void removeInstances(String name) {
+        ArrayList<Instance> toDelete = new ArrayList<Instance>();
+        ArrayList<Instance> instances = mInstances;
+        int count = instances.size();
+        for (int i = 0; i < count; i++) {
+            Instance instance = instances.get(i);
+            if (instance.label.equals(name)) {
+                toDelete.add(instance);
+            }
+        }
+        mInstances.removeAll(toDelete);
+    }
+
+    abstract ArrayList<Prediction> classify(GestureLibrary library, Instance instance);
+}
diff --git a/tests/sketch/src/com/android/gesture/LetterRecognizer.java b/tests/sketch/src/com/android/gesture/LetterRecognizer.java
new file mode 100644
index 0000000..1c15c7d
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/LetterRecognizer.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gesture;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class LetterRecognizer {
+
+    private static final String LOGTAG = "LetterRecognizer";
+
+    public final static int LATTIN_LOWERCASE = 0;
+
+    private SigmoidUnit[] mHiddenLayer;
+
+    private SigmoidUnit[] mOutputLayer;
+
+    private final String[] mClasses;
+
+    private final int mInputCount;
+
+    private class SigmoidUnit {
+
+        private float[] mWeights;
+
+        private SigmoidUnit(float[] weights) {
+            mWeights = weights;
+        }
+
+        private float compute(float[] inputs) {
+            float sum = 0;
+            int count = inputs.length;
+            float[] weights = mWeights;
+            for (int i = 0; i < count; i++) {
+                sum += inputs[i] * weights[i];
+            }
+            sum += weights[weights.length - 1];
+            return 1 / (float)(1 + Math.exp(-sum));
+        }
+    }
+
+    private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) {
+        mInputCount = (int)Math.sqrt(numOfInput);
+        mHiddenLayer = new SigmoidUnit[numOfHidden];
+        mClasses = classes;
+        mOutputLayer = new SigmoidUnit[classes.length];
+    }
+
+    public static LetterRecognizer getLetterRecognizer(Context context, int type) {
+        switch (type) {
+            case LATTIN_LOWERCASE: {
+                return createFromResource(context, com.android.internal.R.raw.lattin_lowercase);
+            }
+        }
+        return null;
+    }
+
+    public ArrayList<Prediction> recognize(Gesture gesture) {
+        return this.classify(GestureUtils.spatialSampling(gesture, mInputCount));
+    }
+
+    private ArrayList<Prediction> classify(float[] vector) {
+        float[] intermediateOutput = compute(mHiddenLayer, vector);
+        float[] output = compute(mOutputLayer, intermediateOutput);
+        ArrayList<Prediction> predictions = new ArrayList<Prediction>();
+        double sum = 0;
+        int count = mClasses.length;
+        for (int i = 0; i < count; i++) {
+            String name = mClasses[i];
+            double score = output[i];
+            sum += score;
+            predictions.add(new Prediction(name, score));
+        }
+
+        for (int i = 0; i < count; i++) {
+            Prediction name = predictions.get(i);
+            name.score /= sum;
+        }
+
+        Collections.sort(predictions, new Comparator<Prediction>() {
+            public int compare(Prediction object1, Prediction object2) {
+                double score1 = object1.score;
+                double score2 = object2.score;
+                if (score1 > score2) {
+                    return -1;
+                } else if (score1 < score2) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+        return predictions;
+    }
+
+    private float[] compute(SigmoidUnit[] layer, float[] input) {
+        float[] output = new float[layer.length];
+        int count = layer.length;
+        for (int i = 0; i < count; i++) {
+            output[i] = layer[i].compute(input);
+        }
+        return output;
+    }
+
+    private static LetterRecognizer createFromResource(Context context, int resourceID) {
+        Resources resources = context.getResources();
+        InputStream stream = resources.openRawResource(resourceID);
+        try {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+
+            String line = reader.readLine();
+            int startIndex = 0;
+            int endIndex = -1;
+            endIndex = line.indexOf(" ", startIndex);
+            int iCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+            startIndex = endIndex + 1;
+            endIndex = line.indexOf(" ", startIndex);
+            int hCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+            startIndex = endIndex + 1;
+            endIndex = line.length();
+            int oCount = Integer.parseInt(line.substring(startIndex, endIndex));
+
+            String[] classes = new String[oCount];
+            line = reader.readLine();
+            startIndex = 0;
+            endIndex = -1;
+            for (int i = 0; i < oCount; i++) {
+                endIndex = line.indexOf(" ", startIndex);
+                classes[i] = line.substring(startIndex, endIndex);
+                startIndex = endIndex + 1;
+            }
+
+            LetterRecognizer classifier = new LetterRecognizer(iCount, hCount, classes);
+            SigmoidUnit[] hiddenLayer = new SigmoidUnit[hCount];
+            SigmoidUnit[] outputLayer = new SigmoidUnit[oCount];
+
+            for (int i = 0; i < hCount; i++) {
+                float[] weights = new float[iCount];
+                line = reader.readLine();
+                startIndex = 0;
+                for (int j = 0; j < iCount; j++) {
+                    endIndex = line.indexOf(" ", startIndex);
+                    weights[j] = Float.parseFloat(line.substring(startIndex, endIndex));
+                    startIndex = endIndex + 1;
+                }
+                hiddenLayer[i] = classifier.new SigmoidUnit(weights);
+            }
+
+            for (int i = 0; i < oCount; i++) {
+                float[] weights = new float[hCount];
+                line = reader.readLine();
+                startIndex = 0;
+                for (int j = 0; j < hCount; j++) {
+                    endIndex = line.indexOf(" ", startIndex);
+                    weights[j] = Float.parseFloat(line.substring(startIndex, endIndex));
+                    startIndex = endIndex + 1;
+                }
+                outputLayer[i] = classifier.new SigmoidUnit(weights);
+            }
+
+            reader.close();
+
+            classifier.mHiddenLayer = hiddenLayer;
+            classifier.mOutputLayer = outputLayer;
+
+            return classifier;
+
+        } catch (IOException ex) {
+            Log.d(LOGTAG, "Failed to save gestures:", ex);
+        }
+        return null;
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java b/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
new file mode 100644
index 0000000..90c3969
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
@@ -0,0 +1,81 @@
+/*
+ * 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.Matrix;
+import android.graphics.Path;
+
+/**
+ * An oriented bounding box
+ */
+public class OrientedBoundingBox {
+
+    public final float squareness;
+
+    public final float width;
+    public final float height;
+
+    public final float orientation; 
+
+    public final float centerX;
+    public final float centerY;
+
+    OrientedBoundingBox(float angle, float cx, float cy, float w, float h) {
+        orientation = angle;
+        width = w;
+        height = h;
+        centerX = cx;
+        centerY = cy;
+        float ratio = w / h;
+        if (ratio > 1) {
+            squareness = 1 / ratio;
+        } else {
+            squareness = ratio;
+        }
+    }
+
+    public Path toPath() {
+        Path path = new Path();
+        float[] point = new float[2];
+        point[0] = -width / 2;
+        point[1] = height / 2;
+        Matrix matrix = new Matrix();
+        matrix.setRotate(orientation);
+        matrix.postTranslate(centerX, centerY);
+        matrix.mapPoints(point);
+        path.moveTo(point[0], point[1]);
+
+        point[0] = -width / 2;
+        point[1] = -height / 2;
+        matrix.mapPoints(point);
+        path.lineTo(point[0], point[1]);
+
+        point[0] = width / 2;
+        point[1] = -height / 2;
+        matrix.mapPoints(point);
+        path.lineTo(point[0], point[1]);
+
+        point[0] = width / 2;
+        point[1] = height / 2;
+        matrix.mapPoints(point);
+        path.lineTo(point[0], point[1]);
+
+        path.close();
+
+        return path;
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/Prediction.java
similarity index 65%
rename from tests/sketch/src/com/android/gesture/recognizer/Prediction.java
rename to tests/sketch/src/com/android/gesture/Prediction.java
index c318754..92d3ba4 100755
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ b/tests/sketch/src/com/android/gesture/Prediction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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,23 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.gesture.recognizer;
+package com.android.gesture;
 
-/**
- * 
- * A recognition result that includes the label and its score
- */
 public class Prediction {
-	public final String label;
-	public double score;
-	
-	public Prediction(String l, double s) {
-		label = l;
-		score = s;
-	}
-	
-	@Override
+    public final String name;
+
+    public double score;
+
+    Prediction(String label, double predictionScore) {
+        name = label;
+        score = predictionScore;
+    }
+
+    @Override
     public String toString() {
-	    return label;
-	}
+        return name;
+    }
 }
diff --git a/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java b/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java
new file mode 100644
index 0000000..0ffc370
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gesture;
+
+import android.graphics.Color;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * TouchThroughGesturing implements the interaction behavior that allows a user
+ * to gesture over a regular UI widget such as ListView and at the same time,
+ * still allows a user to perform basic interactions (clicking, scrolling and panning) 
+ * with the underlying widget.
+ */
+
+public class TouchThroughGesturing implements GestureListener {
+
+    public static final int SINGLE_STROKE = 0;
+
+    public static final int MULTIPLE_STROKE = 1;
+
+    private static final float STROKE_LENGTH_THRESHOLD = 30;
+
+    private static final float SQUARENESS_THRESHOLD = 0.275f;
+    
+    private static final float ANGLE_THRESHOLD = 40;
+
+    public static final int DEFAULT_UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
+
+    private boolean mIsGesturing = false;
+
+    private float mTotalLength;
+
+    private float mX, mY;
+
+    private View mModel;
+
+    private int mGestureType = SINGLE_STROKE;
+    
+    private int mUncertainGestureColor = DEFAULT_UNCERTAIN_GESTURE_COLOR;
+
+    private ArrayList<GestureActionListener> mActionListeners = new ArrayList<GestureActionListener>();
+
+    public TouchThroughGesturing(View model) {
+        mModel = model;
+    }
+
+    /**
+     * 
+     * @param type SINGLE_STROKE or MULTIPLE_STROKE
+     */
+    public void setGestureType(int type) {
+        mGestureType = type;
+    }
+    
+    public void setUncertainGestureColor(int color) {
+        mUncertainGestureColor = color;
+    }
+
+    public void onStartGesture(GestureOverlay overlay, MotionEvent event) {
+        if (mGestureType == MULTIPLE_STROKE) {
+            overlay.cancelFadingOut();
+        }
+        mX = event.getX();
+        mY = event.getY();
+        mTotalLength = 0;
+        mIsGesturing = false;
+        if (mGestureType == SINGLE_STROKE || overlay.getCurrentGesture() == null
+                || overlay.getCurrentGesture().getStrokesCount() == 0) {
+            overlay.setGestureColor(mUncertainGestureColor);
+        }
+        mModel.dispatchTouchEvent(event);
+    }
+
+    public void onGesture(GestureOverlay overlay, MotionEvent event) {
+        if (mIsGesturing) {
+            return;
+        }
+        float x = event.getX();
+        float y = event.getY();
+        float dx = x - mX;
+        float dy = y - mY;
+        mTotalLength += (float)Math.sqrt(dx * dx + dy * dy);
+        mX = x;
+        mY = y;
+
+        if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
+            OrientedBoundingBox bbx = GestureUtils.computeOrientedBBX(overlay.getCurrentStroke());
+            float angle = Math.abs(bbx.orientation);
+            if (angle > 90) {
+                angle = 180 - angle;
+            }
+            if (bbx.squareness > SQUARENESS_THRESHOLD || angle < ANGLE_THRESHOLD) {
+                mIsGesturing = true;
+                overlay.setGestureColor(GestureOverlay.DEFAULT_GESTURE_COLOR);
+                event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
+                        MotionEvent.ACTION_UP, x, y, event.getPressure(), event.getSize(), event
+                                .getMetaState(), event.getXPrecision(), event.getYPrecision(),
+                        event.getDeviceId(), event.getEdgeFlags());
+            }
+        }
+        mModel.dispatchTouchEvent(event);
+    }
+
+    public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
+        if (mIsGesturing) {
+            overlay.clear(true);
+            ArrayList<GestureActionListener> listeners = mActionListeners;
+            int count = listeners.size();
+            for (int i = 0; i < count; i++) {
+                GestureActionListener listener = listeners.get(i);
+                listener.onGesturePerformed(overlay, overlay.getCurrentGesture());
+            }
+        } else {
+            mModel.dispatchTouchEvent(event);
+            overlay.clear(false);
+        }
+    }
+
+    public void addGestureActionListener(GestureActionListener listener) {
+        mActionListeners.add(listener);
+    }
+
+    public void removeGestureActionListener(GestureActionListener listener) {
+        mActionListeners.remove(listener);
+    }
+
+    public boolean isGesturing() {
+        return mIsGesturing;
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/example/ContactAdapter.java b/tests/sketch/src/com/android/gesture/example/ContactAdapter.java
new file mode 100644
index 0000000..008a972
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/ContactAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * 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.example;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+class ContactAdapter extends ArrayAdapter<ContactItem> {
+
+    private LayoutInflater mInflater;
+
+    public ContactAdapter(Activity activity, ArrayList<ContactItem> contacts) {
+        super(activity, 0, contacts);
+        mInflater = activity.getLayoutInflater();
+    }
+
+    @Override
+    public ContactItem getItem(int position) {
+        return super.getItem(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return getItem(position).itemID;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        final ContactItem info = getItem(position);
+
+        View view = convertView;
+        if (view == null) {
+            view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
+            view.setTag(view.findViewById(android.R.id.text1));
+        }
+
+        final TextView textView = (TextView)view.getTag();
+        textView.setText(info.toString());
+
+        return view;
+    }
+
+    public int search(String query) {
+        if (query != null && query.length() > 0) {
+            int start = 0;
+            int end = getCount() - 1;
+            int index = binarySearch(query, start, end);
+            for (index = index - 1; index >= 0; index--) {
+                String str = getItem(index).toString().toLowerCase();
+                if (!str.startsWith(query)) {
+                    return index + 1;
+                }
+                if (index == 0) {
+                    return 0;
+                }
+            }
+            return -1;
+        } else {
+            return -1;
+        }
+    }
+
+    private int binarySearch(String prefix, int start, int end) {
+        if (start > end) {
+            return -1;
+        }
+        int mid = (start + end) / 2;
+        String str = getItem(mid).toString().toLowerCase();
+        if (prefix.compareTo(str) <= 0) {
+            if (str.startsWith(prefix)) {
+                return mid;
+            } else {
+                return binarySearch(prefix, start, mid - 1);
+            }
+        } else {
+            return binarySearch(prefix, mid + 1, end);
+        }
+    }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java b/tests/sketch/src/com/android/gesture/example/ContactItem.java
old mode 100755
new mode 100644
similarity index 62%
copy from tests/sketch/src/com/android/gesture/recognizer/Prediction.java
copy to tests/sketch/src/com/android/gesture/example/ContactItem.java
index c318754..557c4d9
--- a/tests/sketch/src/com/android/gesture/recognizer/Prediction.java
+++ b/tests/sketch/src/com/android/gesture/example/ContactItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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,23 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.gesture.recognizer;
+package com.android.gesture.example;
 
-/**
- * 
- * A recognition result that includes the label and its score
- */
-public class Prediction {
-	public final String label;
-	public double score;
-	
-	public Prediction(String l, double s) {
-		label = l;
-		score = s;
-	}
-	
-	@Override
+
+class ContactItem {
+    final String itemName;
+
+    final long itemID;
+
+    public ContactItem(long id, String name) {
+        itemID = id;
+        itemName = name;
+    }
+
+    @Override
     public String toString() {
-	    return label;
-	}
+        return itemName;
+    }
 }
diff --git a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
new file mode 100644
index 0000000..1d3fdf3
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
@@ -0,0 +1,122 @@
+/*
+ * 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.example;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Contacts.People;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import com.android.gesture.Gesture;
+import com.android.gesture.GestureActionListener;
+import com.android.gesture.GestureOverlay;
+import com.android.gesture.LetterRecognizer;
+import com.android.gesture.Prediction;
+import com.android.gesture.TouchThroughGesturing;
+
+import java.util.ArrayList;
+
+public class ContactListGestureOverlay extends Activity {
+
+    private static final String LOGTAG = "ContactListGestureOverlay";
+    
+    private static final String SORT_ORDER = People.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
+
+    private static final String[] CONTACTS_PROJECTION = new String[] {
+            People._ID, // 0
+            People.DISPLAY_NAME, // 1
+    };
+
+    private GestureOverlay mOverlay;
+
+    private ContactAdapter mContactAdapter;
+
+    private TouchThroughGesturing mGestureProcessor;
+
+    private LetterRecognizer mRecognizer;
+
+    private ListView mContactList;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+        setContentView(R.layout.overlaydemo);
+
+        setProgressBarIndeterminateVisibility(true);
+
+        // create a letter recognizer
+        mRecognizer = LetterRecognizer.getLetterRecognizer(this, LetterRecognizer.LATTIN_LOWERCASE);
+
+        // load the contact list
+        mContactList = (ListView) findViewById(R.id.list);
+        registerForContextMenu(mContactList);
+        mContactList.setTextFilterEnabled(true);
+        mContactList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+                if (!mGestureProcessor.isGesturing()) {
+                    Intent intent = new Intent(Intent.ACTION_VIEW, ContentUris.withAppendedId(
+                            People.CONTENT_URI, id));
+                    startActivity(intent);
+                }
+            }
+        });
+        ContentResolver resolver = getContentResolver();
+        Cursor cursor = resolver.query(People.CONTENT_URI, CONTACTS_PROJECTION, null, null,
+                SORT_ORDER);
+        ArrayList<ContactItem> list = new ArrayList<ContactItem>();
+        while (cursor.moveToNext()) {
+            list.add(new ContactItem(cursor.getLong(0), cursor.getString(1)));
+        }
+        mContactAdapter = new ContactAdapter(this, list);
+        mContactList.setAdapter(mContactAdapter);
+
+        setProgressBarIndeterminateVisibility(false);
+
+        // add a gesture overlay on top of the ListView
+        mOverlay = new GestureOverlay(this);
+        mGestureProcessor = new TouchThroughGesturing(mContactList);
+        mGestureProcessor.setGestureType(TouchThroughGesturing.MULTIPLE_STROKE);
+        mGestureProcessor.addGestureActionListener(new GestureActionListener() {
+            public void onGesturePerformed(GestureOverlay overlay, Gesture gesture) {
+                ArrayList<Prediction> predictions = mRecognizer.recognize(gesture);
+                if (!predictions.isEmpty()) {
+                    Log.v(LOGTAG, "1st Prediction : " + predictions.get(0).name);
+                    Log.v(LOGTAG, "2nd Prediction : " + predictions.get(1).name);
+                    Log.v(LOGTAG, "3rd Prediction : " + predictions.get(2).name);
+                    int index = mContactAdapter.search(predictions.get(0).name);
+                    if (index != -1) {
+                        mContactList.setSelection(index);
+                    }
+                }
+            }
+        });
+        mOverlay.addGestureListener(mGestureProcessor);
+        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
+        this.addContentView(mOverlay, params);
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntry.java b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
new file mode 100644
index 0000000..03a26da
--- /dev/null
+++ b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
@@ -0,0 +1,207 @@
+/*
+ * 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.example;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Environment;
+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.GestureLibrary;
+import com.android.gesture.GestureListener;
+import com.android.gesture.GestureOverlay;
+import com.android.gesture.Prediction;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class GestureEntry extends Activity {
+
+    private static final String PARCEL_KEY = "gesture";
+
+    static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath()
+            + File.separator + "gestureEntry.xml";
+
+    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;
+
+    private GestureOverlay mGesturePad;
+
+    private Spinner mRecognitionResult;
+
+    private GestureLibrary mGestureLibrary;
+
+    private boolean mChangedByRecognizer = false;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.demo);
+
+        // init the gesture library
+        mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME);
+        mGestureLibrary.load();
+
+        // create the spinner for showing the recognition results
+        // the spinner also allows a user to correct a prediction
+        mRecognitionResult = (Spinner) findViewById(R.id.spinner);
+        mRecognitionResult.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                // correct the recognition result by adding the new example
+                if (!mChangedByRecognizer) {
+                    mGestureLibrary.addGesture(parent.getSelectedItem().toString(), mGesturePad
+                            .getCurrentGesture());
+                } else {
+                    mChangedByRecognizer = false;
+                }
+            }
+
+            public void onNothingSelected(AdapterView<?> parent) {
+
+            }
+
+        });
+
+        // create the area for drawing a gesture
+        mGesturePad = (GestureOverlay) findViewById(R.id.drawingpad);
+        mGesturePad.setBackgroundColor(Color.BLACK);
+        mGesturePad.addGestureListener(new GestureListener() {
+            public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
+                recognize(overlay.getCurrentGesture());
+            }
+
+            public void onGesture(GestureOverlay overlay, MotionEvent event) {
+            }
+
+            public void onStartGesture(GestureOverlay overlay, MotionEvent event) {
+                overlay.clear(false);
+            }
+        });
+
+        if (savedInstanceState != null) {
+            Gesture gesture = (Gesture) savedInstanceState.getParcelable(PARCEL_KEY);
+            if (gesture != null) {
+                mGesturePad.setCurrentGesture(gesture);
+            }
+        }
+    }
+
+    @Override
+    protected Dialog onCreateDialog(int id) {
+        LayoutInflater factory = LayoutInflater.from(this);
+        final View textEntryView = factory.inflate(R.layout.newgesture_dialog, null);
+        return new AlertDialog.Builder(GestureEntry.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) {
+                        EditText edittext = (EditText) ((AlertDialog) dialog)
+                                .findViewById(R.id.gesturename_edit);
+                        String text = edittext.getText().toString().trim();
+                        if (text.length() > 0) {
+                            mGestureLibrary.addGesture(text, mGesturePad.getCurrentGesture());
+                        }
+                    }
+                }).setNegativeButton(R.string.newgesture_dialog_cancel,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int whichButton) {
+                    }
+                }).create();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        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) {
+        switch (item.getItemId()) {
+            case NEW_ID:
+                if (mGesturePad.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) {
+        mGestureLibrary.load();
+        mGesturePad.clear(false);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mGestureLibrary.save();
+    }
+
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog) {
+        super.onPrepareDialog(id, dialog);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        Gesture gesture = mGesturePad.getCurrentGesture();
+        if (gesture != null) {
+            outState.putParcelable(PARCEL_KEY, gesture);
+        }
+        mGestureLibrary.save();
+    }
+
+    private void recognize(Gesture gesture) {
+        mChangedByRecognizer = true;
+        ArrayList<Prediction> predictions = mGestureLibrary.recognize(gesture);
+        ArrayAdapter<Prediction> adapter = new ArrayAdapter<Prediction>(this,
+                android.R.layout.simple_spinner_item, predictions);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mRecognitionResult.setAdapter(adapter);
+    }
+
+}
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java b/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
deleted file mode 100755
index 8fee21a..0000000
--- a/tests/sketch/src/com/android/gesture/example/GestureEntryDemo.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.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
index 7ae7fc5..ca54110 100755
--- a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
+++ b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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.
@@ -17,8 +17,6 @@
 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;
@@ -30,228 +28,156 @@
 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 com.android.gesture.GestureLibrary;
+import com.android.gesture.GestureOverlay;
 
 import java.util.ArrayList;
 import java.util.Collections;
 
 /**
- * GestureLibViewer is for viewing existing gestures and 
+ * GestureLibViewer gives an example on how to browse existing gestures and
  * removing unwanted gestures.
  */
 
-public class GestureLibViewer  extends Activity {
-  
-    GesturePad          mView;
-    Spinner             mResult;
-    GestureLib          mRecognizer;
-    ArrayList<Gesture>  mSamples;
-    int                 mCurrentGestureIndex;
+public class GestureLibViewer extends Activity {
+
+    private GestureOverlay mGesturePad;
+
+    private Spinner mGestureCategory;
+
+    private GestureLibrary mGesureLibrary;
+
+    private ArrayList<Gesture> mGestures;
+
+    private int mCurrentGestureIndex;
+
+    private class RemoveGestureListener implements OnClickListener {
+        public void onClick(View v) {
+            if (mGestures.isEmpty()) {
+                return;
+            }
+
+            String name = (String) mGestureCategory.getSelectedItem();
+            Gesture gesture = mGestures.get(mCurrentGestureIndex);
+            mGesureLibrary.removeGesture(name, gesture);
+
+            mGestures = mGesureLibrary.getGestures(name);
+
+            if (mGestures == null) {
+                // delete the entire entry
+                mCurrentGestureIndex = 0;
+                ArrayList<String> list = new ArrayList<String>();
+                list.addAll(mGesureLibrary.getGestureEntries());
+                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);
+                mGestureCategory.setAdapter(adapter);
+            } else {
+                if (mCurrentGestureIndex > mGestures.size() - 1) {
+                    mCurrentGestureIndex--;
+                }
+                gesture = mGestures.get(mCurrentGestureIndex);
+                mGesturePad.setCurrentGesture(gesture);
+                mGesturePad.invalidate();
+            }
+        }
+    }
     
     @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);
+        // create the area for drawing a gesture
+        mGesturePad = (GestureOverlay) findViewById(R.id.drawingpad);
+        mGesturePad.setEnabled(false);
+
+        // init the gesture library
+        mGesureLibrary = new GestureLibrary(GestureEntry.GESTURE_FILE_NAME);
+        mGesureLibrary.load();
+
+        mGestureCategory = (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) {
+        if (!mGesureLibrary.getGestureEntries().isEmpty()) {
+            list.addAll(mGesureLibrary.getGestureEntries());
+            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);
+            mGestureCategory.setAdapter(adapter);
+            mGestures = mGesureLibrary.getGestures(list.get(0));
             mCurrentGestureIndex = 0;
-            Gesture gesture = mSamples.get(mCurrentGestureIndex);
-            mView.setCurrentGesture(gesture);
-            mView.clearDebugPath();
-            mView.addDebugPath(
-                toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+            Gesture gesture = mGestures.get(mCurrentGestureIndex);
+            mGesturePad.setCurrentGesture(gesture);
         }
-        
-        mResult.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+        mGestureCategory.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) {
+                mGestures = mGesureLibrary.getGestures((String) mGestureCategory.getSelectedItem());
+                if (!mGestures.isEmpty()) {
                     mCurrentGestureIndex = 0;
-                    Gesture gesture = mSamples.get(mCurrentGestureIndex);
-                    mView.setCurrentGesture(gesture);
-                    mView.clearDebugPath();
-                    mView.addDebugPath(
-                        toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
+                    Gesture gesture = mGestures.get(mCurrentGestureIndex);
+                    mGesturePad.setCurrentGesture(gesture);
                 }
-                mView.invalidate();
+                mGesturePad.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);
+
+        Button remove = (Button) findViewById(R.id.remove);
+        remove.setOnClickListener(new RemoveGestureListener());
+
+        Button next = (Button) findViewById(R.id.next);
         next.setOnClickListener(new OnClickListener() {
             public void onClick(View v) {
-                // TODO Auto-generated method stub
-                if (mCurrentGestureIndex >= mSamples.size()-1)
+                if (mCurrentGestureIndex >= mGestures.size() - 1) {
                     return;
-                
+                }
                 mCurrentGestureIndex++;
-                Gesture gesture = mSamples.get(mCurrentGestureIndex);
-                mView.setCurrentGesture(gesture);
-                mView.clearDebugPath();
-                mView.addDebugPath(
-                    toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
-                mView.invalidate();
+                Gesture gesture = mGestures.get(mCurrentGestureIndex);
+                mGesturePad.setCurrentGesture(gesture);
+                mGesturePad.invalidate();
             }
         });
 
-        Button previous = (Button)this.findViewById(R.id.previous);
+        Button previous = (Button) findViewById(R.id.previous);
         previous.setOnClickListener(new OnClickListener() {
             public void onClick(View v) {
-                // TODO Auto-generated method stub
-                if (mCurrentGestureIndex >= 1 &&
-                    mSamples.isEmpty() == false) {
+                if (mCurrentGestureIndex >= 1 && !mGestures.isEmpty()) {
                     mCurrentGestureIndex--;
-                    Gesture gesture = mSamples.get(mCurrentGestureIndex);
-                    mView.setCurrentGesture(gesture);
-                    mView.clearDebugPath();
-                    mView.addDebugPath(
-                        toPath(mRecognizer.getClassifier().getInstance(gesture.getID())));
-                    mView.invalidate();
+                    Gesture gesture = mGestures.get(mCurrentGestureIndex);
+                    mGesturePad.setCurrentGesture(gesture);
+                    mGesturePad.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;
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            mGesureLibrary.save();
+            setResult(RESULT_OK);
+            finish();
+            return true;
+        } else {
+            return false;
+        }
     }
-    
+
     @Override
     protected void onPause() {
-        // TODO Auto-generated method stub
         super.onPause();
-        mRecognizer.save();
+        mGesureLibrary.save();
     }
 
     @Override
     protected void onSaveInstanceState(Bundle outState) {
-        // TODO Auto-generated method stub
         super.onSaveInstanceState(outState);
-        mRecognizer.save();
+        mGesureLibrary.save();
     }
 }
diff --git a/tests/sketch/src/com/android/gesture/recognizer/Classifier.java b/tests/sketch/src/com/android/gesture/recognizer/Classifier.java
deleted file mode 100755
index 584e0a5..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/Classifier.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.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
deleted file mode 100755
index 2eaa1c2..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/Instance.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.android.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
deleted file mode 100755
index cb8a9d3..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/NearestNeighbor.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.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/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java b/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java
deleted file mode 100755
index 9146b95..0000000
--- a/tests/sketch/src/com/android/gesture/recognizer/RecognitionUtil.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture.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));
-    }
-
-}