Merge change 23461 into eclair

* changes:
  Mimetypes in ContactsProvider2 shouldn't overlap with those in ContactsProvider
diff --git a/api/current.xml b/api/current.xml
index 3e616a4..46dfd89 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -18039,6 +18039,50 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_FOREGROUND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_PERSISTENT_PROCESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_STARTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_SYSTEM_PROCESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="activeSince"
  type="long"
  transient="false"
@@ -18069,6 +18113,16 @@
  visibility="public"
 >
 </field>
+<field name="flags"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="foreground"
  type="boolean"
  transient="false"
@@ -18139,6 +18193,16 @@
  visibility="public"
 >
 </field>
+<field name="uid"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ActivityManager.RunningTaskInfo"
  extends="java.lang.Object"
@@ -97544,6 +97608,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.os.Parcelable">
+</implements>
 <constructor name="Debug.MemoryInfo"
  type="android.os.Debug.MemoryInfo"
  static="false"
@@ -97552,6 +97618,55 @@
  visibility="public"
 >
 </constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="readFromParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.os.Parcel">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dalvikPrivateDirty"
  type="int"
  transient="false"
@@ -167386,6 +167501,171 @@
 <parameter name="url" type="java.lang.String">
 </parameter>
 </method>
+<field name="ERROR_AUTHENTICATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_BAD_URL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_CONNECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_FAILED_SSL_HANDSHAKE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_FILE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-13"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_FILE_NOT_FOUND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-14"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_HOST_LOOKUP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_IO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_PROXY_AUTHENTICATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_REDIRECT_LOOP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_TIMEOUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_TOO_MANY_REQUESTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-15"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_UNSUPPORTED_AUTH_SCHEME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_UNSUPPORTED_SCHEME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="WebViewDatabase"
  extends="java.lang.Object"
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index fd9e708..7adaf57 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -546,6 +546,9 @@
         case PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE:
             s = "INSTALL_FAILED_CPU_ABI_INCOMPATIBLE";
             break;
+        case PackageManager.INSTALL_FAILED_MISSING_FEATURE:
+            s = "INSTALL_FAILED_MISSING_FEATURE";
+            break;
         case PackageManager.INSTALL_PARSE_FAILED_NOT_APK:
             s = "INSTALL_PARSE_FAILED_NOT_APK";
             break;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 07520c9d..ad06fa9 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -289,6 +289,11 @@
         public int pid;
         
         /**
+         * The UID that owns this service.
+         */
+        public int uid;
+        
+        /**
          * The name of the process this service runs in.
          */
         public String process;
@@ -299,7 +304,7 @@
         public boolean foreground;
         
         /**
-         * The time when the service was first made activity, either by someone
+         * The time when the service was first made active, either by someone
          * starting or binding to it.
          */
         public long activeSince;
@@ -332,6 +337,35 @@
          */
         public long restarting;
         
+        /**
+         * Bit for {@link #flags}: set if this service has been
+         * explicitly started.
+         */
+        public static final int FLAG_STARTED = 1<<0;
+        
+        /**
+         * Bit for {@link #flags}: set if the service has asked to
+         * run as a foreground process.
+         */
+        public static final int FLAG_FOREGROUND = 1<<1;
+        
+        /**
+         * Bit for {@link #flags): set if the service is running in a
+         * core system process.
+         */
+        public static final int FLAG_SYSTEM_PROCESS = 1<<2;
+        
+        /**
+         * Bit for {@link #flags): set if the service is running in a
+         * persistent process.
+         */
+        public static final int FLAG_PERSISTENT_PROCESS = 1<<3;
+        
+        /**
+         * Running flags.
+         */
+        public int flags;
+        
         public RunningServiceInfo() {
         }
 
@@ -342,6 +376,7 @@
         public void writeToParcel(Parcel dest, int flags) {
             ComponentName.writeToParcel(service, dest);
             dest.writeInt(pid);
+            dest.writeInt(uid);
             dest.writeString(process);
             dest.writeInt(foreground ? 1 : 0);
             dest.writeLong(activeSince);
@@ -350,11 +385,13 @@
             dest.writeInt(crashCount);
             dest.writeLong(lastActivityTime);
             dest.writeLong(restarting);
+            dest.writeInt(this.flags);
         }
 
         public void readFromParcel(Parcel source) {
             service = ComponentName.readFromParcel(source);
             pid = source.readInt();
+            uid = source.readInt();
             process = source.readString();
             foreground = source.readInt() != 0;
             activeSince = source.readLong();
@@ -363,6 +400,7 @@
             crashCount = source.readInt();
             lastActivityTime = source.readLong();
             restarting = source.readLong();
+            flags = source.readInt();
         }
         
         public static final Creator<RunningServiceInfo> CREATOR = new Creator<RunningServiceInfo>() {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index d14ec15..1bb21b9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -29,6 +29,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -1107,6 +1108,16 @@
             reply.writeNoException();
             return true;
         }
+        
+        case GET_PROCESS_MEMORY_INFO_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int pid = data.readInt();
+            Debug.MemoryInfo mi = new Debug.MemoryInfo();
+            getProcessMemoryInfo(pid, mi);
+            reply.writeNoException();
+            mi.writeToParcel(reply, 0);
+            return true;
+        }
         }
         
         return super.onTransact(code, data, reply, flags);
@@ -2424,6 +2435,19 @@
         data.recycle();
         reply.recycle();
     }
-        
+    
+    public void getProcessMemoryInfo(int pid, Debug.MemoryInfo outInfo)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(pid);
+        mRemote.transact(GET_PROCESS_MEMORY_INFO_TRANSACTION, data, reply, 0);
+        reply.readException();
+        outInfo.readFromParcel(reply);
+        data.recycle();
+        reply.recycle();
+    }
+    
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1e915b4..b4e57e0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1546,6 +1546,10 @@
             }
         }
         
+        public void getMemoryInfo(Debug.MemoryInfo outInfo) {
+            Debug.getMemoryInfo(outInfo);
+        }
+        
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             long nativeMax = Debug.getNativeHeapSize() / 1024;
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index ad64465..15bf9ed 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -26,6 +26,7 @@
 import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.IBinder;
@@ -370,6 +371,16 @@
             scheduleDestroyBackupAgent(appInfo);
             return true;
         }
+
+        case GET_MEMORY_INFO_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            Debug.MemoryInfo mi = new Debug.MemoryInfo();
+            getMemoryInfo(mi);
+            reply.writeNoException();
+            mi.writeToParcel(reply, 0);
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -756,5 +767,16 @@
                 IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+    
+    public void getMemoryInfo(Debug.MemoryInfo outInfo) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        mRemote.transact(GET_MEMORY_INFO_TRANSACTION, data, reply, 0);
+        reply.readException();
+        outInfo.readFromParcel(reply);
+        data.recycle();
+        reply.recycle();
+    }
 }
 
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c3e7224..64daea9 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -30,6 +30,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.Debug;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.IInterface;
@@ -272,6 +273,9 @@
     
     public void closeSystemDialogs(String reason) throws RemoteException;
     
+    public void getProcessMemoryInfo(int pid, Debug.MemoryInfo outInfo)
+            throws RemoteException;
+    
     /*
      * Private non-Binder interfaces
      */
@@ -428,4 +432,5 @@
     int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
     int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
     int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
+    int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 6faaa34..da9a957 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -25,6 +25,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.IBinder;
@@ -97,6 +98,7 @@
     void profilerControl(boolean start, String path, ParcelFileDescriptor fd)
             throws RemoteException;
     void setSchedulingGroup(int group) throws RemoteException;
+    void getMemoryInfo(Debug.MemoryInfo outInfo) throws RemoteException;
     
     String descriptor = "android.app.IApplicationThread";
 
@@ -130,4 +132,5 @@
     int SET_SCHEDULING_GROUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
     int SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
     int SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
+    int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
 }
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index d17775e..1edcb0a 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -111,8 +111,7 @@
                 if (mSyncThread != null
                         && mSyncThread.mSyncContext.getISyncContext().asBinder()
                         == syncContext.asBinder()) {
-                    // TODO: figure out why canceling causes a hang
-//                    mSyncThread.interrupt();
+                    mSyncThread.interrupt();
                 }
             }
         }
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 5d7af69d..57bf3f7 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -62,53 +62,53 @@
      */
     public enum ConflictAlgorithm {
         /**
-         *  When a constraint violation occurs, an immediate ROLLBACK occurs, 
-         * thus ending the current transaction, and the command aborts with a 
-         * return code of SQLITE_CONSTRAINT. If no transaction is active 
+         *  When a constraint violation occurs, an immediate ROLLBACK occurs,
+         * thus ending the current transaction, and the command aborts with a
+         * return code of SQLITE_CONSTRAINT. If no transaction is active
          * (other than the implied transaction that is created on every command)
          *  then this algorithm works the same as ABORT.
          */
         ROLLBACK("ROLLBACK"),
-        
+
         /**
-         * When a constraint violation occurs,no ROLLBACK is executed 
-         * so changes from prior commands within the same transaction 
+         * When a constraint violation occurs,no ROLLBACK is executed
+         * so changes from prior commands within the same transaction
          * are preserved. This is the default behavior.
          */
         ABORT("ABORT"),
-        
+
         /**
-         * When a constraint violation occurs, the command aborts with a return 
-         * code SQLITE_CONSTRAINT. But any changes to the database that 
-         * the command made prior to encountering the constraint violation 
+         * When a constraint violation occurs, the command aborts with a return
+         * code SQLITE_CONSTRAINT. But any changes to the database that
+         * the command made prior to encountering the constraint violation
          * are preserved and are not backed out.
          */
         FAIL("FAIL"),
-        
+
         /**
-         * When a constraint violation occurs, the one row that contains 
-         * the constraint violation is not inserted or changed. 
-         * But the command continues executing normally. Other rows before and 
-         * after the row that contained the constraint violation continue to be 
+         * When a constraint violation occurs, the one row that contains
+         * the constraint violation is not inserted or changed.
+         * But the command continues executing normally. Other rows before and
+         * after the row that contained the constraint violation continue to be
          * inserted or updated normally. No error is returned.
          */
         IGNORE("IGNORE"),
-        
+
         /**
          * When a UNIQUE constraint violation occurs, the pre-existing rows that
-         * are causing the constraint violation are removed prior to inserting 
+         * are causing the constraint violation are removed prior to inserting
          * or updating the current row. Thus the insert or update always occurs.
-         * The command continues executing normally. No error is returned. 
+         * The command continues executing normally. No error is returned.
          * If a NOT NULL constraint violation occurs, the NULL value is replaced
-         * by the default value for that column. If the column has no default 
-         * value, then the ABORT algorithm is used. If a CHECK constraint 
-         * violation occurs then the IGNORE algorithm is used. When this conflict 
-         * resolution strategy deletes rows in order to satisfy a constraint, 
+         * by the default value for that column. If the column has no default
+         * value, then the ABORT algorithm is used. If a CHECK constraint
+         * violation occurs then the IGNORE algorithm is used. When this conflict
+         * resolution strategy deletes rows in order to satisfy a constraint,
          * it does not invoke delete triggers on those rows.
          *  This behavior might change in a future release.
          */
         REPLACE("REPLACE");
-        
+
         private final String mValue;
         ConflictAlgorithm(String value) {
             mValue = value;
@@ -117,7 +117,7 @@
             return mValue;
         }
     }
-    
+
     /**
      * Maximum Length Of A LIKE Or GLOB Pattern
      * The pattern matching algorithm used in the default LIKE and GLOB implementation
@@ -180,17 +180,19 @@
 
     private long mLockAcquiredWallTime = 0L;
     private long mLockAcquiredThreadTime = 0L;
-    
+
     // limit the frequency of complaints about each database to one within 20 sec
-    // unless run command adb shell setprop log.tag.Database VERBOSE  
+    // unless run command adb shell setprop log.tag.Database VERBOSE
     private static final int LOCK_WARNING_WINDOW_IN_MS = 20000;
     /** If the lock is held this long then a warning will be printed when it is released. */
     private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS = 300;
     private static final int LOCK_ACQUIRED_WARNING_THREAD_TIME_IN_MS = 100;
     private static final int LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT = 2000;
 
+    private static final int SLEEP_AFTER_YIELD_QUANTUM = 500;
+
     private long mLastLockMessageTime = 0L;
-    
+
     /** Used by native code, do not rename */
     /* package */ int mNativeHandle = 0;
 
@@ -205,15 +207,15 @@
 
     /** The optional factory to use when creating new Cursors */
     private CursorFactory mFactory;
-    
+
     private WeakHashMap<SQLiteClosable, Object> mPrograms;
- 
+
     private final RuntimeException mLeakedException;
 
     // package visible, since callers will access directly to minimize overhead in the case
     // that logging is not enabled.
     /* package */ final boolean mLogStats;
-    
+
     /**
      * @param closable
      */
@@ -225,7 +227,7 @@
             unlock();
         }
     }
-    
+
     void removeSQLiteClosable(SQLiteClosable closable) {
         lock();
         try {
@@ -233,8 +235,8 @@
         } finally {
             unlock();
         }
-    }    
-   
+    }
+
     @Override
     protected void onAllReferencesReleased() {
         if (isOpen()) {
@@ -245,10 +247,10 @@
     /**
      * Attempts to release memory that SQLite holds but does not require to
      * operate properly. Typically this memory will come from the page cache.
-     * 
+     *
      * @return the number of bytes actually released
      */
-    static public native int releaseMemory(); 
+    static public native int releaseMemory();
 
     /**
      * Control whether or not the SQLiteDatabase is made thread-safe by using locks
@@ -284,7 +286,7 @@
      * touch the native sqlite3* object since it is single threaded and uses
      * a polling lock contention algorithm. The lock is recursive, and may be acquired
      * multiple times by the same thread. This is a no-op if mLockingEnabled is false.
-     * 
+     *
      * @see #unlock()
      */
     /* package */ void lock() {
@@ -320,7 +322,7 @@
 
     /**
      * Releases the database lock. This is a no-op if mLockingEnabled is false.
-     * 
+     *
      * @see #unlock()
      */
     /* package */ void unlock() {
@@ -350,7 +352,7 @@
     private void checkLockHoldTime() {
         // Use elapsed real-time since the CPU may sleep when waiting for IO
         long elapsedTime = SystemClock.elapsedRealtime();
-        long lockedTime = elapsedTime - mLockAcquiredWallTime;                
+        long lockedTime = elapsedTime - mLockAcquiredWallTime;
         if (lockedTime < LOCK_ACQUIRED_WARNING_TIME_IN_MS_ALWAYS_PRINT &&
                 !Log.isLoggable(TAG, Log.VERBOSE) &&
                 (elapsedTime - mLastLockMessageTime) < LOCK_WARNING_WINDOW_IN_MS) {
@@ -567,10 +569,21 @@
             }
         }
         if (sleepAfterYieldDelay > 0) {
-            try {
-                Thread.sleep(sleepAfterYieldDelay);
-            } catch (InterruptedException e) {
-                Thread.interrupted();
+            // Sleep for up to sleepAfterYieldDelay milliseconds, waking up periodically to
+            // check if anyone is using the database.  If the database is not contended,
+            // retake the lock and return.
+            long remainingDelay = sleepAfterYieldDelay;
+            while (remainingDelay > 0) {
+                try {
+                    Thread.sleep(remainingDelay < SLEEP_AFTER_YIELD_QUANTUM ?
+                            remainingDelay : SLEEP_AFTER_YIELD_QUANTUM);
+                } catch (InterruptedException e) {
+                    Thread.interrupted();
+                }
+                remainingDelay -= SLEEP_AFTER_YIELD_QUANTUM;
+                if (mLock.getQueueLength() == 0) {
+                    break;
+                }
             }
         }
         beginTransaction();
@@ -720,9 +733,9 @@
             if (program != null) {
                 program.onAllReferencesReleasedFromContainer();
             }
-        }        
+        }
     }
-    
+
     /**
      * Native call to close the database.
      */
@@ -1157,8 +1170,8 @@
 
     /**
      * Runs the provided SQL and returns a cursor over the result set.
-     * The cursor will read an initial set of rows and the return to the caller. 
-     * It will continue to read in batches and send data changed notifications 
+     * The cursor will read an initial set of rows and the return to the caller.
+     * It will continue to read in batches and send data changed notifications
      * when the later batches are ready.
      * @param sql the SQL query. The SQL string must not be ; terminated
      * @param selectionArgs You may include ?s in where clause in the query,
@@ -1167,19 +1180,19 @@
      * @param initialRead set the initial count of items to read from the cursor
      * @param maxRead set the count of items to read on each iteration after the first
      * @return A {@link Cursor} object, which is positioned before the first entry
-     * 
+     *
      * This work is incomplete and not fully tested or reviewed, so currently
      * hidden.
      * @hide
      */
-    public Cursor rawQuery(String sql, String[] selectionArgs, 
+    public Cursor rawQuery(String sql, String[] selectionArgs,
             int initialRead, int maxRead) {
         SQLiteCursor c = (SQLiteCursor)rawQueryWithFactory(
                 null, sql, selectionArgs, null);
         c.setLoadStyle(initialRead, maxRead);
         return c;
     }
-    
+
     /**
      * Convenience method for inserting a row into the database.
      *
@@ -1232,7 +1245,7 @@
      */
     public long replace(String table, String nullColumnHack, ContentValues initialValues) {
         try {
-            return insertWithOnConflict(table, nullColumnHack, initialValues, 
+            return insertWithOnConflict(table, nullColumnHack, initialValues,
                     ConflictAlgorithm.REPLACE);
         } catch (SQLException e) {
             Log.e(TAG, "Error inserting " + initialValues, e);
@@ -1254,7 +1267,7 @@
      */
     public long replaceOrThrow(String table, String nullColumnHack,
             ContentValues initialValues) throws SQLException {
-        return insertWithOnConflict(table, nullColumnHack, initialValues, 
+        return insertWithOnConflict(table, nullColumnHack, initialValues,
                 ConflictAlgorithm.REPLACE);
     }
 
@@ -1410,7 +1423,7 @@
     public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
         return updateWithOnConflict(table, values, whereClause, whereArgs, null);
     }
-    
+
     /**
      * Convenience method for updating rows in the database.
      *
@@ -1423,7 +1436,7 @@
      * @return the number of rows affected
      * @hide
      */
-    public int updateWithOnConflict(String table, ContentValues values, 
+    public int updateWithOnConflict(String table, ContentValues values,
             String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) {
         if (!isOpen()) {
             throw new IllegalStateException("database not open");
@@ -1440,7 +1453,7 @@
             sql.append(algorithm.value());
             sql.append(" ");
         }
-        
+
         sql.append(table);
         sql.append(" SET ");
 
@@ -1601,7 +1614,7 @@
         mFlags = flags;
         mPath = path;
         mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats"));
-        
+
         mLeakedException = new IllegalStateException(path +
             " SQLiteDatabase created and never closed");
         mFactory = factory;
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index b0fc78e..5352cf6 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -104,7 +104,7 @@
      * This class is used to retrieved various statistics about the memory mappings for this
      * process. The returns info broken down by dalvik, native, and other. All results are in kB.
      */
-    public static class MemoryInfo {
+    public static class MemoryInfo implements Parcelable {
         /** The proportional set size for dalvik. */
         public int dalvikPss;
         /** The private dirty pages used by dalvik. */
@@ -125,6 +125,50 @@
         public int otherPrivateDirty;
         /** The shared dirty pages used by everything else. */
         public int otherSharedDirty;
+        
+        public MemoryInfo() {
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(dalvikPss);
+            dest.writeInt(dalvikPrivateDirty);
+            dest.writeInt(dalvikSharedDirty);
+            dest.writeInt(nativePss);
+            dest.writeInt(nativePrivateDirty);
+            dest.writeInt(nativeSharedDirty);
+            dest.writeInt(otherPss);
+            dest.writeInt(otherPrivateDirty);
+            dest.writeInt(otherSharedDirty);
+        }
+
+        public void readFromParcel(Parcel source) {
+            dalvikPss = source.readInt();
+            dalvikPrivateDirty = source.readInt();
+            dalvikSharedDirty = source.readInt();
+            nativePss = source.readInt();
+            nativePrivateDirty = source.readInt();
+            nativeSharedDirty = source.readInt();
+            otherPss = source.readInt();
+            otherPrivateDirty = source.readInt();
+            otherSharedDirty = source.readInt();
+        }
+        
+        public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
+            public MemoryInfo createFromParcel(Parcel source) {
+                return new MemoryInfo(source);
+            }
+            public MemoryInfo[] newArray(int size) {
+                return new MemoryInfo[size];
+            }
+        };
+
+        private MemoryInfo(Parcel source) {
+            readFromParcel(source);
+        }
     }
 
 
@@ -556,6 +600,13 @@
     public static native void getMemoryInfo(MemoryInfo memoryInfo);
 
     /**
+     * Note: currently only works when the requested pid has the same UID
+     * as the caller.
+     * @hide
+     */
+    public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
+
+    /**
      * Establish an object allocation limit in the current thread.  Useful
      * for catching regressions in code that is expected to operate
      * without causing any allocations.
diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java
index 8e8d46a..0064bf2 100644
--- a/core/java/android/pim/vcard/ContactStruct.java
+++ b/core/java/android/pim/vcard/ContactStruct.java
@@ -773,11 +773,7 @@
                     } else if (typeString.equals(Constants.ATTR_TYPE_WORK)) {
                         type = Email.TYPE_WORK;
                     } else if (typeString.equals(Constants.ATTR_TYPE_CELL)) {
-                        // We do not have TYPE_MOBILE yet.
-                        // TODO: modify this code when TYPE_MOBILE is supported.
-                        type = Email.TYPE_CUSTOM;
-                        label =
-                            android.provider.Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME;
+                        type = Email.TYPE_MOBILE;
                     } else {
                         if (typeString.startsWith("X-") && type < 0) {
                             typeString = typeString.substring(2);
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 283d00b..5a09c64f 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -967,6 +967,9 @@
         if (contentValuesList != null) {
             for (ContentValues contentValues : contentValuesList) {
                 byte[] data = contentValues.getAsByteArray(Photo.PHOTO);
+                if (data == null) {
+                    continue;
+                }
                 final String photoType;
                 // Use some heuristics for guessing the format of the image.
                 // TODO: there should be some general API for detecting the file format.
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 975c2ff..79a7cf8 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -283,10 +283,12 @@
             String value = null;
             int len = Integer.valueOf(propValues[1]);
             if (len > 0) {
-                value = "";
+                StringBuilder str = new StringBuilder();
                 for (int i = 2; i < propValues.length; i++) {
-                    value = value + propValues[i] + ',';
+                    str.append(propValues[i]);
+                    str.append(",");
                 }
+                value = str.toString();
             }
             mBluetoothService.setProperty(name, value);
         } else if (name.equals("Powered")) {
@@ -331,10 +333,12 @@
             String uuid = null;
             int len = Integer.valueOf(propValues[1]);
             if (len > 0) {
-                uuid = "";
+                StringBuilder str = new StringBuilder();
                 for (int i = 2; i < propValues.length; i++) {
-                    uuid = uuid + propValues[i] + ",";
+                    str.append(propValues[i]);
+                    str.append(",");
                 }
+                uuid = str.toString();
             }
             mBluetoothService.setRemoteDeviceProperty(address, name, uuid);
         } else if (name.equals("Paired")) {
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 413f6a8..21104c8 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -551,20 +551,21 @@
 
         for (int i = 0; i < properties.length; i++) {
             String name = properties[i];
-            String newValue;
+            String newValue = null;
             int len;
             if (name == null) {
                 Log.e(TAG, "Error:Adapter Property at index" + i + "is null");
                 continue;
             }
             if (name.equals("Devices")) {
+                StringBuilder str = new StringBuilder();
                 len = Integer.valueOf(properties[++i]);
-                if (len != 0)
-                    newValue = "";
-                else
-                    newValue = null;
                 for (int j = 0; j < len; j++) {
-                    newValue += properties[++i] + ",";
+                    str.append(properties[++i]);
+                    str.append(",");
+                }
+                if (len > 0) {
+                    newValue = str.toString();
                 }
             } else {
                 newValue = properties[++i];
@@ -837,32 +838,32 @@
          * We get a DeviceFound signal every time RSSI changes or name changes.
          * Don't create a new Map object every time */
         Map<String, String> propertyValues = mDeviceProperties.get(address);
-        if (propertyValues != null) {
-            propertyValues.clear();
-        } else {
+        if (propertyValues == null) {
             propertyValues = new HashMap<String, String>();
         }
 
         for (int i = 0; i < properties.length; i++) {
             String name = properties[i];
-            String newValue;
+            String newValue = null;
             int len;
             if (name == null) {
                 Log.e(TAG, "Error: Remote Device Property at index" + i + "is null");
                 continue;
             }
             if (name.equals("UUIDs") || name.equals("Nodes")) {
+                StringBuilder str = new StringBuilder();
                 len = Integer.valueOf(properties[++i]);
-                if (len != 0)
-                    newValue = "";
-                else
-                    newValue = null;
                 for (int j = 0; j < len; j++) {
-                    newValue += properties[++i] + ",";
+                    str.append(properties[++i]);
+                    str.append(",");
+                }
+                if (len > 0) {
+                    newValue = str.toString();
                 }
             } else {
                 newValue = properties[++i];
             }
+
             propertyValues.put(name, newValue);
         }
         mDeviceProperties.put(address, propertyValues);
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 29dc2ea52..a92800d 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1527,7 +1527,7 @@
                     if (bm != null) {
                         workPaint.set(paint);
                         Styled.measureText(paint, workPaint, text,
-                                           offset, offset + 1, null);
+                                           j, j + 2, null);
 
                         float wid = (float) bm.getWidth() *
                                     -workPaint.ascent() / bm.getHeight();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 425ccab..d569220 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -46,7 +46,6 @@
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.util.Config;
-import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Pool;
diff --git a/core/java/android/webkit/ContentLoader.java b/core/java/android/webkit/ContentLoader.java
index 27cd6b5..19aa087 100644
--- a/core/java/android/webkit/ContentLoader.java
+++ b/core/java/android/webkit/ContentLoader.java
@@ -57,6 +57,16 @@
 
     }
 
+    private String errString(Exception ex) {
+        String exMessage = ex.getMessage();
+        String errString = mContext.getString(
+                com.android.internal.R.string.httpErrorFileNotFound);
+        if (exMessage != null) {
+            errString += " " + exMessage;
+        }
+        return errString;
+    }
+
     @Override
     protected boolean setupStreamAndSendStatus() {
         Uri uri = Uri.parse(mUrl);
@@ -73,28 +83,16 @@
             mDataStream = mContext.getContentResolver().openInputStream(uri);
             mHandler.status(1, 1, 0, "OK");
         } catch (java.io.FileNotFoundException ex) {
-            mHandler.error(
-                    EventHandler.FILE_NOT_FOUND_ERROR,
-                    mContext.getString(
-                            com.android.internal.R.string.httpErrorFileNotFound) +
-                    " " + ex.getMessage());
+            mHandler.error(EventHandler.FILE_NOT_FOUND_ERROR, errString(ex));
             return false;
 
         } catch (java.io.IOException ex) {
-            mHandler.error(
-                    EventHandler.FILE_ERROR,
-                    mContext.getString(
-                            com.android.internal.R.string.httpErrorFileNotFound) +
-                    " " + ex.getMessage());
+            mHandler.error(EventHandler.FILE_ERROR, errString(ex));
             return false;
         } catch (RuntimeException ex) {
             // readExceptionWithFileNotFoundExceptionFromParcel in DatabaseUtils
             // can throw a serial of RuntimeException. Catch them all here.
-            mHandler.error(
-                    EventHandler.FILE_ERROR,
-                    mContext.getString(
-                            com.android.internal.R.string.httpErrorFileNotFound) +
-                    " " + ex.getMessage());
+            mHandler.error(EventHandler.FILE_ERROR, errString(ex));
             return false;
         }
         return true;
diff --git a/core/java/android/webkit/FileLoader.java b/core/java/android/webkit/FileLoader.java
index 54a4c1d..085f1f4 100644
--- a/core/java/android/webkit/FileLoader.java
+++ b/core/java/android/webkit/FileLoader.java
@@ -72,6 +72,15 @@
         }
     }
 
+    private String errString(Exception ex) {
+        String exMessage = ex.getMessage();
+        String errString = mContext.getString(R.string.httpErrorFileNotFound);
+        if (exMessage != null) {
+            errString += " " + exMessage;
+        }
+        return errString;
+    }
+
     @Override
     protected boolean setupStreamAndSendStatus() {
         try {
@@ -95,16 +104,11 @@
             mHandler.status(1, 1, 0, "OK");
 
         } catch (java.io.FileNotFoundException ex) {
-            mHandler.error(
-                    EventHandler.FILE_NOT_FOUND_ERROR,
-                    mContext.getString(R.string.httpErrorFileNotFound) +
-                    " " + ex.getMessage());
+            mHandler.error(EventHandler.FILE_NOT_FOUND_ERROR, errString(ex));
             return false;
 
         } catch (java.io.IOException ex) {
-            mHandler.error(EventHandler.FILE_ERROR,
-                           mContext.getString(R.string.httpErrorFileNotFound) +
-                           " " + ex.getMessage());
+            mHandler.error(EventHandler.FILE_ERROR, errString(ex));
             return false;
         }
         return true;
diff --git a/core/java/android/GoogleLocationSettingManager.java b/core/java/android/webkit/GoogleLocationSettingManager.java
similarity index 100%
rename from core/java/android/GoogleLocationSettingManager.java
rename to core/java/android/webkit/GoogleLocationSettingManager.java
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 43c76a8..1a5b2eb 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -606,6 +606,7 @@
                 // before calling it.
                 if (mCacheLoader != null) {
                     mCacheLoader.load();
+                    mFromCache = true;
                     if (DebugFlags.LOAD_LISTENER) {
                         Log.v(LOGTAG, "LoadListener cache load url=" + url());
                     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e39e3f1..792fdf2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -342,6 +342,9 @@
      */
     VelocityTracker mVelocityTracker;
     private int mMaximumFling;
+    private float mLastVelocity;
+    private float mLastVelX;
+    private float mLastVelY;
 
     // use this flag to control whether enabling the new double tap zoom
     static final boolean ENABLE_DOUBLETAP_ZOOM = true;
@@ -1795,6 +1798,13 @@
                 , contentToView(x.right), contentToView(x.bottom));
     }
 
+    // stop the scroll animation, and don't let a subsequent fling add
+    // to the existing velocity
+    private void abortAnimation() {
+        mScroller.abortAnimation();
+        mLastVelocity = 0;
+    }
+
     /* call from webcoreview.draw(), so we're still executing in the UI thread
     */
     private void recordNewContentSize(int w, int h, boolean updateLayout) {
@@ -1819,7 +1829,7 @@
                 mScrollY = pinLocY(mScrollY);
                 // android.util.Log.d("skia", "recordNewContentSize -
                 // abortAnimation");
-                mScroller.abortAnimation(); // just in case
+                abortAnimation(); // just in case
                 if (oldX != mScrollX || oldY != mScrollY) {
                     sendOurVisibleRect();
                 }
@@ -2339,7 +2349,7 @@
                     animationDuration > 0 ? animationDuration : computeDuration(dx, dy));
             invalidate();
         } else {
-            mScroller.abortAnimation(); // just in case
+            abortAnimation(); // just in case
             scrollTo(x, y);
         }
         return true;
@@ -2963,7 +2973,7 @@
         mLastTouchX = halfW;
         int halfH = height >> 1;
         mLastTouchY = halfH;
-        mScroller.abortAnimation();
+        abortAnimation();
         mZoomScrollStart = System.currentTimeMillis();
         Rect zoomFrame = scrollZoomFrame(width, height
                 , scrollZoomMagScale(mZoomScrollInvLimit));
@@ -3850,6 +3860,9 @@
                     mLastScrollY = mZoomScrollY;
                     // If two taps are close, ignore the first tap
                 } else if (!mScroller.isFinished()) {
+                    // stop the current scroll animation, but if this is
+                    // the start of a fling, allow it to add to the current
+                    // fling's velocity
                     mScroller.abortAnimation();
                     mTouchMode = TOUCH_DRAG_START_MODE;
                     mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
@@ -4110,6 +4123,7 @@
                             doFling();
                             break;
                         }
+                        mLastVelocity = 0;
                         WebViewCore.resumeUpdate(mWebViewCore);
                         break;
                     case TOUCH_DRAG_START_MODE:
@@ -4475,6 +4489,27 @@
             vx = vx * 3 / 4;
             vy = vy * 3 / 4;
         }
+        float currentVelocity = mScroller.getCurrVelocity();
+        if (mLastVelocity > 0 && currentVelocity > 0) {
+            float deltaR = (float) (Math.abs(Math.atan2(mLastVelY, mLastVelX)
+                    - Math.atan2(vy, vx)));
+            final float circle = (float) (Math.PI) * 2.0f;
+            if (deltaR > circle * 0.9f || deltaR < circle * 0.1f) {
+                vx += currentVelocity * mLastVelX / mLastVelocity;
+                vy += currentVelocity * mLastVelY / mLastVelocity;
+                if (DebugFlags.WEB_VIEW) {
+                    Log.v(LOGTAG, "doFling vx= " + vx + " vy=" + vy);
+                }
+            } else if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "doFling missed " + deltaR / circle);
+            }
+        } else if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "doFling start last=" + mLastVelocity
+                    + " current=" + currentVelocity);
+        }
+        mLastVelX = vx;
+        mLastVelY = vy;
+        mLastVelocity = (float) Math.hypot(vx, vy);
 
         mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY);
         // TODO: duration is calculated based on velocity, if the range is
@@ -4683,7 +4718,7 @@
         mLastTouchY = y + (float) (mWebTextView.getTop() - mScrollY);
         mLastTouchTime = eventTime;
         if (!mScroller.isFinished()) {
-            mScroller.abortAnimation();
+            abortAnimation();
             mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
         }
         mSnapScrollMode = SNAP_NONE;
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index a185779..30dea74 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -92,14 +92,46 @@
         cancelMsg.sendToTarget();
     }
 
+    // These ints must match up to the hidden values in EventHandler.
+    /** Generic error */
+    public static final int ERROR_UNKNOWN = -1;
+    /** Server or proxy hostname lookup failed */
+    public static final int ERROR_HOST_LOOKUP = -2;
+    /** Unsupported authentication scheme (not basic or digest) */
+    public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
+    /** User authentication failed on server */
+    public static final int ERROR_AUTHENTICATION = -4;
+    /** User authentication failed on proxy */
+    public static final int ERROR_PROXY_AUTHENTICATION = -5;
+    /** Failed to connect to the server */
+    public static final int ERROR_CONNECT = -6;
+    /** Failed to read or write to the server */
+    public static final int ERROR_IO = -7;
+    /** Connection timed out */
+    public static final int ERROR_TIMEOUT = -8;
+    /** Too many redirects */
+    public static final int ERROR_REDIRECT_LOOP = -9;
+    /** Unsupported URI scheme */
+    public static final int ERROR_UNSUPPORTED_SCHEME = -10;
+    /** Failed to perform SSL handshake */
+    public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
+    /** Malformed URL */
+    public static final int ERROR_BAD_URL = -12;
+    /** Generic file error */
+    public static final int ERROR_FILE = -13;
+    /** File not found */
+    public static final int ERROR_FILE_NOT_FOUND = -14;
+    /** Too many requests during this load */
+    public static final int ERROR_TOO_MANY_REQUESTS = -15;
+
     /**
-     * Report an error to an activity. These errors come up from WebCore, and
-     * are network errors.
-     * 
+     * Report an error to the host application. These errors are unrecoverable
+     * (i.e. the main resource is unavailable). The errorCode parameter
+     * corresponds to one of the ERROR_* constants.
      * @param view The WebView that is initiating the callback.
-     * @param errorCode The HTTP error code.
-     * @param description A String description.
-     * @param failingUrl The url that failed.
+     * @param errorCode The error code corresponding to an ERROR_* value.
+     * @param description A String describing the error.
+     * @param failingUrl The url that failed to load.
      */
     public void onReceivedError(WebView view, int errorCode,
             String description, String failingUrl) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 67721c9..2f292d5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1996,7 +1996,10 @@
                 if (y != mLastY) {
                     deltaY -= mMotionCorrection;
                     int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
-                    trackMotionScroll(deltaY, incrementalDeltaY);
+                    // No need to do all this work if we're not going to move anyway
+                    if (incrementalDeltaY != 0) {
+                        trackMotionScroll(deltaY, incrementalDeltaY);
+                    }
 
                     // Check to see if we have bumped into the scroll limit
                     View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
@@ -2063,7 +2066,7 @@
                             if (mSelector != null) {
                                 Drawable d = mSelector.getCurrent();
                                 if (d != null && d instanceof TransitionDrawable) {
-                                    ((TransitionDrawable)d).resetTransition();
+                                    ((TransitionDrawable) d).resetTransition();
                                 }
                             }
                             postDelayed(new Runnable() {
@@ -2087,15 +2090,27 @@
                 mTouchMode = TOUCH_MODE_REST;
                 break;
             case TOUCH_MODE_SCROLL:
-                final VelocityTracker velocityTracker = mVelocityTracker;
-                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-                final int initialVelocity = (int) velocityTracker.getYVelocity();
-                if (Math.abs(initialVelocity) > mMinimumVelocity && (getChildCount() > 0)) {
-                    if (mFlingRunnable == null) {
-                        mFlingRunnable = new FlingRunnable();
+                final int childCount = getChildCount();
+                if (childCount > 0) {
+                    if (mFirstPosition == 0 && getChildAt(0).getTop() >= mListPadding.top &&
+                            mFirstPosition + childCount < mItemCount &&
+                            getChildAt(childCount - 1).getBottom() <=
+                                    getHeight() - mListPadding.bottom) {
+                        mTouchMode = TOUCH_MODE_REST;
+                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+                    } else {
+                        final VelocityTracker velocityTracker = mVelocityTracker;
+                        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                        final int initialVelocity = (int) velocityTracker.getYVelocity();
+    
+                        if (Math.abs(initialVelocity) > mMinimumVelocity) {
+                            if (mFlingRunnable == null) {
+                                mFlingRunnable = new FlingRunnable();
+                            }
+                            reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+                            mFlingRunnable.start(-initialVelocity);
+                        }
                     }
-                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
-                    mFlingRunnable.start(-initialVelocity);
                 } else {
                     mTouchMode = TOUCH_MODE_REST;
                     reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 993b7cb..6316864 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1328,19 +1328,23 @@
 
             // Make sure we are 1) Too low, and 2) Either there are more rows below the
             // last row or the last row is scrolled off the bottom of the drawable area
-            if (topOffset > 0 && (lastPosition < mItemCount - 1 || lastBottom > end))  {
-                if (lastPosition == mItemCount - 1 ) {
-                    // Don't pull the bottom too far up
-                    topOffset = Math.min(topOffset, lastBottom - end);
-                }
-                // Move everything up
-                offsetChildrenTopAndBottom(-topOffset);
-                if (lastPosition < mItemCount - 1) {
-                    // Fill the gap that was opened below the last position with more rows, if
-                    // possible
-                    fillDown(lastPosition + 1, lastChild.getBottom() + mDividerHeight);
-                    // Close up the remaining gap
-                    adjustViewsUpOrDown();
+            if (topOffset > 0) {
+                if (lastPosition < mItemCount - 1 || lastBottom > end)  {
+                    if (lastPosition == mItemCount - 1) {
+                        // Don't pull the bottom too far up
+                        topOffset = Math.min(topOffset, lastBottom - end);
+                    }
+                    // Move everything up
+                    offsetChildrenTopAndBottom(-topOffset);
+                    if (lastPosition < mItemCount - 1) {
+                        // Fill the gap that was opened below the last position with more rows, if
+                        // possible
+                        fillDown(lastPosition + 1, lastChild.getBottom() + mDividerHeight);
+                        // Close up the remaining gap
+                        adjustViewsUpOrDown();
+                    }
+                } else if (lastPosition == mItemCount - 1) {
+                    adjustViewsUpOrDown();                    
                 }
             }
         }
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index b179a13..2f28d9f 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -651,6 +651,7 @@
 
             if (mProgress > max) {
                 mProgress = max;
+                refreshProgress(R.id.progress, mProgress, false);
             }
         }
     }
diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java
index 381641f..11dab02 100644
--- a/core/java/android/widget/Scroller.java
+++ b/core/java/android/widget/Scroller.java
@@ -133,6 +133,17 @@
     }
     
     /**
+     * @hide
+     * Returns the current velocity.
+     *
+     * @return The original velocity less the deceleration. Result may be
+     * negative.
+     */
+    public float getCurrVelocity() {
+        return mVelocity - mDeceleration * timePassed() / 2000.0f;
+    }
+
+    /**
      * Returns the start X offset in the scroll. 
      * 
      * @return The start X offset as an absolute distance from the origin.
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 41044db..4041346 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -1,16 +1,16 @@
 /**
  ** Copyright 2007, The Android Open Source Project
  **
- ** Licensed under the Apache License, Version 2.0 (the "License"); 
- ** you may not use this file except in compliance with the License. 
- ** You may obtain a copy of the License at 
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
  **
- **     http://www.apache.org/licenses/LICENSE-2.0 
+ **     http://www.apache.org/licenses/LICENSE-2.0
  **
- ** Unless required by applicable law or agreed to in writing, software 
- ** distributed under the License is distributed on an "AS IS" BASIS, 
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- ** See the License for the specific language governing permissions and 
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
  ** limitations under the License.
  */
 
@@ -53,18 +53,18 @@
     MallocHelper() {
         mData = 0;
     }
-    
+
     ~MallocHelper() {
         if (mData != 0) {
             free(mData);
         }
     }
-    
+
     void* alloc(size_t size) {
         mData = malloc(size);
         return mData;
     }
-    
+
 private:
     void* mData;
 };
@@ -88,17 +88,17 @@
     int result = POLY_CLIP_OUT;
     float* pTransformed = 0;
     int transformedIndexCount = 0;
-    
+
     if ( indexCount < 3 ) {
         return POLY_CLIP_OUT;
     }
-    
+
     // Find out how many vertices we need to transform
     // We transform every vertex between the min and max indices, inclusive.
     // This is OK for the data sets we expect to use with this function, but
     // for other loads it might be better to use a more sophisticated vertex
     // cache of some sort.
-    
+
     int minIndex = 65536;
     int maxIndex = -1;
     for(int i = 0; i < indexCount; i++) {
@@ -110,18 +110,18 @@
             maxIndex = index;
         }
     }
-    
+
     if ( maxIndex * 3 > positionsLength) {
         return -1;
     }
-    
+
     transformedIndexCount = maxIndex - minIndex + 1;
     pTransformed = (float*) mallocHelper.alloc(transformedIndexCount * 4 * sizeof(float));
-    
+
     if (pTransformed == 0 ) {
         return -2;
     }
-    
+
     // Transform the vertices
     {
         const float* pSrc = pPositions + 3 * minIndex;
@@ -130,9 +130,9 @@
             mx4transform(pSrc[0], pSrc[1], pSrc[2], 1.0f, pWS,  pDst);
         }
     }
-    
+
     // Clip the triangles
-    
+
     Poly poly;
     float* pDest = & poly.vert[0].sx;
     for (int i = 0; i < indexCount; i += 3) {
@@ -166,14 +166,14 @@
             mEnv->ReleasePrimitiveArrayCritical(mRef, mBase, mReleaseParam);
         }
     }
-    
+
     // We seperate the bounds check from the initialization because we want to
     // be able to bounds-check multiple arrays, and we can't throw an exception
     // after we've called GetPrimitiveArrayCritical.
-    
+
     // Return true if the bounds check succeeded
     // Else instruct the runtime to throw an exception
-    
+
     bool check() {
         if ( ! mRef) {
             mEnv->ThrowNew(gIAEClass, "array == null");
@@ -190,9 +190,9 @@
         }
         return true;
     }
-    
+
     // Bind the array.
-    
+
     void bind() {
         mBase = (T*) mEnv->GetPrimitiveArrayCritical(mRef, (jboolean *) 0);
         mData = mBase + mOffset;
@@ -201,10 +201,10 @@
     void commitChanges() {
         mReleaseParam = 0;
     }
-    
+
     T* mData;
     int mLength;
-    
+
 private:
     T* mBase;
     JNIEnv* mEnv;
@@ -226,29 +226,29 @@
 inline float distance(float x, float y, float z) {
     return sqrtf(distance2(x, y, z));
 }
-    
+
 static
 void util_computeBoundingSphere(JNIEnv *env, jclass clazz,
         jfloatArray positions_ref, jint positionsOffset, jint positionsCount,
         jfloatArray sphere_ref, jint sphereOffset) {
     FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
     FloatArrayHelper sphere(env, sphere_ref, sphereOffset, 4);
-    
+
     bool checkOK = positions.check() && sphere.check();
         if (! checkOK) {
         return;
     }
-    
+
     positions.bind();
     sphere.bind();
-    
+
     if ( positionsCount < 1 ) {
         env->ThrowNew(gIAEClass, "positionsCount < 1");
         return;
     }
-    
+
     const float* pSrc = positions.mData;
-    
+
     // find bounding box
     float x0 = *pSrc++;
     float x1 = x0;
@@ -256,7 +256,7 @@
     float y1 = y0;
     float z0 = *pSrc++;
     float z1 = z0;
-    
+
     for(int i = 1; i < positionsCount; i++) {
         {
             float x = *pSrc++;
@@ -286,7 +286,7 @@
             }
         }
     }
-    
+
     // Because we know our input meshes fit pretty well into bounding boxes,
     // just take the diagonal of the box as defining our sphere.
     float* pSphere = sphere.mData;
@@ -297,7 +297,7 @@
     *pSphere++ = y0 + dy * 0.5f;
     *pSphere++ = z0 + dz * 0.5f;
     *pSphere++ = distance(dx, dy, dz) * 0.5f;
-    
+
     sphere.commitChanges();
 }
 
@@ -344,7 +344,7 @@
     normalizePlane(f);
     f+= 4;
 
-    // left    
+    // left
     f[0] = m3  + m[0];
     f[1] = m7  + m[4];
     f[2] = m11 + m[8];
@@ -396,20 +396,20 @@
     FloatArrayHelper mvp(env, mvp_ref, mvpOffset, 16);
     FloatArrayHelper spheres(env, spheres_ref, spheresOffset, spheresCount * 4);
     IntArrayHelper results(env, results_ref, resultsOffset, resultsCapacity);
-    
+
     bool initializedOK = mvp.check() && spheres.check() && results.check();
         if (! initializedOK) {
         return -1;
     }
-    
+
     mvp.bind();
     spheres.bind();
     results.bind();
-        
+
     computeFrustum(mvp.mData, frustum);
-    
+
     // Cull the spheres
-    
+
     pSphere = spheres.mData;
     pResults = results.mData;
     outputCount = 0;
@@ -436,27 +436,27 @@
         jfloatArray ws_ref, jint wsOffset,
         jfloatArray positions_ref, jint positionsOffset,
         jcharArray indices_ref, jint indicesOffset, jint indexCount) {
-    
+
     FloatArrayHelper ws(env, ws_ref, wsOffset, 16);
     FloatArrayHelper positions(env, positions_ref, positionsOffset, 0);
     UnsignedShortArrayHelper indices(env, indices_ref, indicesOffset, 0);
-    
+
     bool checkOK = ws.check() && positions.check() && indices.check();
     if (! checkOK) {
         // Return value will be ignored, because an exception has been thrown.
         return -1;
     }
-    
+
     if (indices.mLength < indexCount) {
         env->ThrowNew(gIAEClass, "length < offset + indexCount");
         // Return value will be ignored, because an exception has been thrown.
         return -1;
     }
-    
+
     ws.bind();
     positions.bind();
     indices.bind();
-        
+
     return visibilityTest(ws.mData,
             positions.mData, positions.mLength,
             indices.mData, indexCount);
@@ -496,19 +496,19 @@
     FloatArrayHelper resultMat(env, result_ref, resultOffset, 16);
     FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
     FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 16);
-    
+
     bool checkOK = resultMat.check() && lhs.check() && rhs.check();
-    
+
     if ( !checkOK ) {
         return;
     }
-    
+
     resultMat.bind();
     lhs.bind();
     rhs.bind();
-    
+
     multiplyMM(resultMat.mData, lhs.mData, rhs.mData);
-    
+
     resultMat.commitChanges();
 }
 
@@ -527,19 +527,19 @@
     FloatArrayHelper resultV(env, result_ref, resultOffset, 4);
     FloatArrayHelper lhs(env, lhs_ref, lhsOffset, 16);
     FloatArrayHelper rhs(env, rhs_ref, rhsOffset, 4);
-    
+
     bool checkOK = resultV.check() && lhs.check() && rhs.check();
-    
+
     if ( !checkOK ) {
         return;
     }
-    
+
     resultV.bind();
     lhs.bind();
     rhs.bind();
-    
+
     multiplyMV(resultV.mData, lhs.mData, rhs.mData);
-    
+
     resultV.commitChanges();
 }
 
@@ -550,7 +550,7 @@
 void nativeUtilsClassInit(JNIEnv *env, jclass clazz)
 {
     jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
-    nativeBitmapID = env->GetFieldID(bitmapClass, "mNativeBitmap", "I");    
+    nativeBitmapID = env->GetFieldID(bitmapClass, "mNativeBitmap", "I");
 }
 
 static int checkFormat(SkBitmap::Config config, int format, int type)
@@ -653,7 +653,7 @@
     }
     int err = checkFormat(config, internalformat, type);
     if (err)
-        return err; 
+        return err;
     bitmap.lockPixels();
     const int w = bitmap.width();
     const int h = bitmap.height();
@@ -665,14 +665,15 @@
         }
         const size_t size = bitmap.getSize();
         const size_t palette_size = 256*sizeof(SkPMColor);
-        void* const data = malloc(size + palette_size);
+        const size_t imageSize = size + palette_size;
+        void* const data = malloc(imageSize);
         if (data) {
             void* const pixels = (char*)data + palette_size;
             SkColorTable* ctable = bitmap.getColorTable();
             memcpy(data, ctable->lockColors(), ctable->count() * sizeof(SkPMColor));
             memcpy(pixels, p, size);
             ctable->unlockColors(false);
-            glCompressedTexImage2D(target, level, internalformat, w, h, border, 0, data);
+            glCompressedTexImage2D(target, level, internalformat, w, h, border, imageSize, data);
             free(data);
         } else {
             err = -1;
@@ -700,7 +701,7 @@
     }
     int err = checkFormat(config, format, type);
     if (err)
-        return err; 
+        return err;
     bitmap.lockPixels();
     const int w = bitmap.width();
     const int h = bitmap.height();
@@ -723,22 +724,22 @@
 }
 
 static JNINativeMethod gMatrixMethods[] = {
-    { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM }, 
-    { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV }, 
+    { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
+    { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
 };
 
 static JNINativeMethod gVisiblityMethods[] = {
-    { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere }, 
+    { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere },
     { "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres },
-    { "visibilityTest", "([FI[FI[CII)I", (void*)util_visibilityTest }, 
+    { "visibilityTest", "([FI[FI[CII)I", (void*)util_visibilityTest },
 };
 
 static JNINativeMethod gUtilsMethods[] = {
     {"nativeClassInit", "()V",                          (void*)nativeUtilsClassInit },
-    { "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat }, 
-    { "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType }, 
-    { "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D }, 
-    { "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D }, 
+    { "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat },
+    { "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType },
+    { "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
+    { "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D },
 };
 
 typedef struct _ClassRegistrationInfo {
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index 9c4f7c7..0aeaadc 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -54,6 +54,8 @@
 static const int TYPE_SCO = 2;
 static const int TYPE_L2CAP = 3;  // TODO: Test l2cap code paths
 
+static const int RFCOMM_SO_SNDBUF = 70 * 1024;  // 70 KB send buffer
+
 static struct asocket *get_socketData(JNIEnv *env, jobject obj) {
     struct asocket *s =
             (struct asocket *) env->GetIntField(obj, field_mSocketData);
@@ -87,6 +89,7 @@
 
     int fd;
     int lm = 0;
+    int sndbuf;
     jboolean auth;
     jboolean encrypt;
     jint type;
@@ -131,7 +134,16 @@
 
     if (lm) {
         if (setsockopt(fd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
-            LOGV("setsockopt() failed, throwing");
+            LOGV("setsockopt(RFCOMM_LM) failed, throwing");
+            jniThrowIOException(env, errno);
+            return;
+        }
+    }
+
+    if (type == TYPE_RFCOMM) {
+        sndbuf = RFCOMM_SO_SNDBUF;
+        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
+            LOGV("setsockopt(SO_SNDBUF) failed, throwing");
             jniThrowIOException(env, errno);
             return;
         }
@@ -274,16 +286,21 @@
     }
 
     if (bind(s->fd, addr, addr_sz)) {
+        LOGV("...bind(%d) gave errno %d", s->fd, errno);
         jniThrowIOException(env, errno);
         return;
     }
 
     if (listen(s->fd, 1)) {
+        LOGV("...listen(%d) gave errno %d", s->fd, errno);
         jniThrowIOException(env, errno);
         return;
     }
 
+    LOGV("...bindListenNative(%d) success", s->fd);
+
     return;
+
 #endif
     jniThrowIOException(env, ENOSYS);
 }
diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp
index 7d6e24f..4c213a31 100644
--- a/core/jni/android_emoji_EmojiFactory.cpp
+++ b/core/jni/android_emoji_EmojiFactory.cpp
@@ -197,8 +197,11 @@
 
 static void android_emoji_EmojiFactory_destructor(
     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+  /*
+  // Must not delete this object!!
   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
   delete factory;
+  */
 }
 
 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index b4c60f1..3ee404ad 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -200,12 +200,13 @@
     fclose(fp);
 }
 
-static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
+static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
+        jint pid, jobject object)
 {
     stats_t stats;
     memset(&stats, 0, sizeof(stats_t));
     
-    load_maps(getpid(), &stats);
+    load_maps(pid, &stats);
 
     env->SetIntField(object, dalvikPss_field, stats.dalvikPss);
     env->SetIntField(object, dalvikPrivateDirty_field, stats.dalvikPrivateDirty);
@@ -220,6 +221,11 @@
     env->SetIntField(object, otherSharedDirty_field, stats.otherSharedDirty);
 }
 
+static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject object)
+{
+    android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object);
+}
+
 static jint read_binder_stat(const char* stat)
 {
     FILE* fp = fopen(BINDER_STATS, "r");
@@ -281,6 +287,8 @@
             (void*) android_os_Debug_getNativeHeapFreeSize },
     { "getMemoryInfo",          "(Landroid/os/Debug$MemoryInfo;)V",
             (void*) android_os_Debug_getDirtyPages },
+    { "getMemoryInfo",          "(ILandroid/os/Debug$MemoryInfo;)V",
+            (void*) android_os_Debug_getDirtyPagesPid },
     { "getBinderSentTransactions", "()I",
             (void*) android_os_Debug_getBinderSentTransactions },
     { "getBinderReceivedTransactions", "()I",
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_connected_1x.png b/core/res/res/drawable-hdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..58d2dbb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_in_1x.png b/core/res/res/drawable-hdpi/stat_sys_data_in_1x.png
new file mode 100644
index 0000000..cd1afe9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_inandout_1x.png b/core/res/res/drawable-hdpi/stat_sys_data_inandout_1x.png
new file mode 100644
index 0000000..c398d6f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_out_1x.png b/core/res/res/drawable-hdpi/stat_sys_data_out_1x.png
new file mode 100644
index 0000000..e1eb5b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_connected_1x.png b/core/res/res/drawable-mdpi/stat_sys_data_connected_1x.png
similarity index 100%
rename from core/res/res/drawable/stat_sys_data_connected_1x.png
rename to core/res/res/drawable-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_in_1x.png b/core/res/res/drawable-mdpi/stat_sys_data_in_1x.png
similarity index 100%
rename from core/res/res/drawable/stat_sys_data_in_1x.png
rename to core/res/res/drawable-mdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_inandout_1x.png b/core/res/res/drawable-mdpi/stat_sys_data_inandout_1x.png
similarity index 100%
rename from core/res/res/drawable/stat_sys_data_inandout_1x.png
rename to core/res/res/drawable-mdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_out_1x.png b/core/res/res/drawable-mdpi/stat_sys_data_out_1x.png
similarity index 100%
rename from core/res/res/drawable/stat_sys_data_out_1x.png
rename to core/res/res/drawable-mdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index ef1a1ea..a5dadbc 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -375,7 +375,7 @@
     </ul>
     <ul>
     <?cs if:android.whichdoc != "online" ?>
-      <li><a href="<?cs var:toroot ?>../samples">
+      <li><a href="<?cs var:toroot ?>../platforms/android-<?cs var:sdk.version ?>/samples">
             <span class="en">Sample Code</span>
           &raquo;</a></li>
     <?cs else ?>
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 2626735..0248985 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -6,7 +6,8 @@
 <dt>syntax:</dt>
 <dd>
 <pre class="stx">
-&lt;uses-feature android:<a href="#glEsVersion">glEsVersion</a>=["true" | "false"] /&gt;
+&lt;uses-feature android:<a href="#glEsVersion">glEsVersion</a>="<em>integer</em>"
+              android:<a href="#name">name</a>="<em>string</em>" /&gt;
 </pre>
 </dd>
 
@@ -14,7 +15,7 @@
 <dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
 
 <dt>description:</dt>
-<dd>This element specifies specific features used by the application.
+<dd>This element specifies a specific feature used by the application.
 Android provides some features that may not be equally supported by all
 Android devices. In a manner similar to the <code><a href="uses-sdk-element.html">&lt;uses-sdk></a></code> 
 element, this element allows an application to specify which potentially variable
@@ -23,6 +24,11 @@
 
 <p>For example, an application might specify that it requires a certain version of Open GL.
 If a device does not support that version of Open GL, then it will not allow installation of the application.</p>
+
+<p class="note"><strong>Note:</strong>
+For each feature required by your application, you must include a new {@code
+&lt;uses-feature>} element. Multiple features cannot be declared in one 
+instance of this element.</p>
 </dd> 
 
 
@@ -38,6 +44,30 @@
 </dl>
 </dd>
 
+<dd>
+<dl class="attr"><dt><a name="name"></a>{@code android:name}</dt>
+  <dd>The name of a feature required by the application. 
+  The value must be one of the following accepted strings:
+  
+  <table> 
+    <tr> 
+       <th>Value</th> 
+       <th>Description</th> 
+    </tr><tr> 
+       <td>"{@code android.hardware.camera}"</td> 
+       <td>The application requires a camera.</td> 
+    </tr><tr> 
+       <td>"{@code android.hardware.camera.autofocus}"</td> 
+       <td>The application requires a camera with auto-focus capability.
+       As a prerequisite, "{@code android.hardware.camera}" must also be declared
+       with a separate {@code &lt;uses-feature>} element.</td> 
+    </tr>
+  </table>
+  
+  </dd>
+</dl>
+</dd>
+
 <!-- ##api level indication## -->
 <dt>introduced in:</dt>
 <dd>API Level 4</dd>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 2abb777..f60a7be 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -337,19 +337,26 @@
      */
     public static Bitmap decodeResource(Resources res, int id, Options opts) {
         Bitmap bm = null;
-
+        InputStream is = null; 
+        
         try {
             final TypedValue value = new TypedValue();
-            final InputStream is = res.openRawResource(id, value);
+            is = res.openRawResource(id, value);
 
             bm = decodeResourceStream(res, value, is, null, opts);
-            is.close();
-        } catch (java.io.IOException e) {
+        } catch (Exception e) {
             /*  do nothing.
                 If the exception happened on open, bm will be null.
                 If it happened on close, bm is still valid.
             */
+        } finally {
+            try {
+                if (is != null) is.close();
+            } catch (IOException e) {
+                // Ignore
+            }
         }
+
         return bm;
     }
 
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 3001c743..536f71c 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -16,19 +16,15 @@
 
 package android.renderscript;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Array;
-
 import java.io.IOException;
 import java.io.InputStream;
 
 import android.content.res.Resources;
+import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.os.Bundle;
-import android.renderscript.Type;
-import android.util.Config;
 import android.util.Log;
+import android.util.TypedValue;
 
 /**
  * @hide
@@ -52,7 +48,7 @@
     }
 
     public void data(int[] d) {
-        int size = 0;
+        int size;
         if(mType != null && mType.mElement != null) {
             size = mType.mElement.mSize;
             for(int ct=0; ct < mType.mValues.length; ct++) {
@@ -71,7 +67,7 @@
     }
 
     public void data(float[] d) {
-        int size = 0;
+        int size;
         if(mType != null && mType.mElement != null) {
             size = mType.mElement.mSize;
             for(int ct=0; ct < mType.mValues.length; ct++) {
@@ -245,8 +241,29 @@
     static public Allocation createFromBitmapResource(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips)
         throws IllegalArgumentException {
 
-        Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
-        return createFromBitmap(rs, b, dstFmt, genMips);
+        InputStream is = null;
+        try {
+            final TypedValue value = new TypedValue();
+            is = res.openRawResource(id, value);
+
+            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+            int allocationId = rs.nAllocationCreateFromAssetStream(dstFmt.mPredefinedID, genMips,
+                    asset);
+
+            return new Allocation(allocationId, rs, null);            
+        } catch (Exception e) {
+            // Ignore
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+
+        return null;
     }
 
     static public Allocation createFromBitmapResourceBoxed(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips)
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index ee7b702..0f188f6 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -16,13 +16,10 @@
 
 package android.renderscript;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.lang.reflect.Field;
 
-import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.renderscript.Type;
+import android.graphics.BitmapFactory;
 import android.util.Config;
 import android.util.Log;
 import android.view.Surface;
@@ -35,6 +32,7 @@
 public class RenderScript {
     static final String LOG_TAG = "libRS_jni";
     private static final boolean DEBUG  = false;
+    @SuppressWarnings({"UnusedDeclaration", "deprecation"})
     private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
 
 
@@ -43,6 +41,7 @@
      * We use a class initializer to allow the native code to cache some
      * field offsets.
      */
+    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
     private static boolean sInitialized;
     native private static void _nInit();
 
@@ -95,6 +94,7 @@
     native int  nAllocationCreateSized(int elem, int count);
     native int  nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp);
     native int  nAllocationCreateFromBitmapBoxed(int dstFmt, boolean genMips, Bitmap bmp);
+    native int  nAllocationCreateFromAssetStream(int dstFmt, boolean genMips, int assetStream);
 
     native void nAllocationUploadToTexture(int alloc, int baseMioLevel);
     native void nAllocationUploadToBufferObject(int alloc);
@@ -188,6 +188,7 @@
 
     private int     mDev;
     private int     mContext;
+    @SuppressWarnings({"FieldCanBeLocal"})
     private Surface mSurface;
 
     private static boolean mElementsInitialized = false;
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 2550181..558146d 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -26,7 +26,13 @@
 #include <ui/Surface.h>
 
 #include <core/SkBitmap.h>
+#include <core/SkPixelRef.h>
+#include <core/SkStream.h>
+#include <core/SkTemplates.h>
+#include <images/SkImageDecoder.h>
 
+#include <utils/Asset.h>
+#include <utils/ResourceTypes.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
@@ -397,6 +403,32 @@
 }
 
 static int
+nAllocationCreateFromAssetStream(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jint native_asset)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+
+    Asset* asset = reinterpret_cast<Asset*>(native_asset);
+    SkBitmap bitmap;
+    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
+            &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
+
+    SkBitmap::Config config = bitmap.getConfig();
+
+    RsElementPredefined e = SkBitmapToPredefined(config);
+
+    if (e != RS_ELEMENT_USER_U8) {
+        bitmap.lockPixels();
+        const int w = bitmap.width();
+        const int h = bitmap.height();
+        const void* ptr = bitmap.getPixels();
+        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
+        bitmap.unlockPixels();
+        return id;
+    }
+    return 0;
+}
+
+static int
 nAllocationCreateFromBitmapBoxed(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jobject jbitmap)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
@@ -494,7 +526,7 @@
     LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jint *ptr = _env->GetIntArrayElements(data, NULL);
     rsAllocationRead(con, (RsAllocation)alloc, ptr);
-    _env->ReleaseIntArrayElements(data, ptr, JNI_COMMIT);
+    _env->ReleaseIntArrayElements(data, ptr, 0);
 }
 
 static void
@@ -505,7 +537,7 @@
     LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
     rsAllocationRead(con, (RsAllocation)alloc, ptr);
-    _env->ReleaseFloatArrayElements(data, ptr, JNI_COMMIT);
+    _env->ReleaseFloatArrayElements(data, ptr, 0);
 }
 
 
@@ -1239,6 +1271,7 @@
 {"nAllocationCreateSized",         "(II)I",                                (void*)nAllocationCreateSized },
 {"nAllocationCreateFromBitmap",    "(IZLandroid/graphics/Bitmap;)I",       (void*)nAllocationCreateFromBitmap },
 {"nAllocationCreateFromBitmapBoxed","(IZLandroid/graphics/Bitmap;)I",      (void*)nAllocationCreateFromBitmapBoxed },
+{"nAllocationCreateFromAssetStream","(IZI)I",                              (void*)nAllocationCreateFromAssetStream },
 {"nAllocationUploadToTexture",     "(II)V",                                (void*)nAllocationUploadToTexture },
 {"nAllocationUploadToBufferObject","(I)V",                                 (void*)nAllocationUploadToBufferObject },
 {"nAllocationData",                "(I[II)V",                              (void*)nAllocationData_i },
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 3a419b5..ef71641 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -1449,6 +1449,8 @@
         int j = activeTracks.indexOf(t);
         if (j >= 0) {
             mActiveTracks.add(t);
+            // force buffer refilling and no ramp volume when the track is mixed for the first time
+            t->mFillingUpStatus = Track::FS_FILLING;
         }
     }
 }
@@ -3512,10 +3514,11 @@
             if (tracks.size()) {
                 dstThread->putTracks(tracks, activeTracks);
             }
-            dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
         }
     }
 
+    dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
+
     return NO_ERROR;
 }
 
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 8326361..94ced22 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -105,9 +105,6 @@
      */
     public static final String KEY_LOCATION_CHANGED = "location";
 
-    /** @hide */
-    public static final String SYSTEM_DIR = "/data/system/location";
-
     // Map from LocationListeners to their associated ListenerTransport objects
     private HashMap<LocationListener,ListenerTransport> mListeners =
         new HashMap<LocationListener,ListenerTransport>();
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index d578c81..aba40b3 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -340,6 +340,7 @@
         ParsePosition pos = new ParsePosition(0);
         try {
             Date date = sFormatter.parse(dateTimeString, pos);
+            if (date == null) return -1;
             return date.getTime();
         } catch (IllegalArgumentException ex) {
             return -1;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index eaad4fc..3a065ae 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1321,6 +1321,10 @@
         return;
     }
 
+    // We're going to temporarily give up the lock while reading data
+    // from the source. A certain client unfortunately chose to have the
+    // thread supplying input data and reading output data be the same...
+
     MediaBuffer *srcBuffer;
     status_t err;
     if (mSeekTimeUs >= 0) {
@@ -1328,10 +1332,13 @@
         options.setSeekTo(mSeekTimeUs);
         mSeekTimeUs = -1;
 
+        mLock.unlock();
         err = mSource->read(&srcBuffer, &options);
     } else {
+        mLock.unlock();
         err = mSource->read(&srcBuffer);
     }
+    mLock.lock();
 
     OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
     OMX_TICKS timestamp = 0;
diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java
index 3513215..ea14307 100644
--- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java
+++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsBroadcastReceiver.java
@@ -16,6 +16,7 @@
 
 package com.android.providers.subscribedfeeds;
 
+import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -35,7 +36,10 @@
 
     public void onReceive(Context context, Intent intent) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "Received intent " + intent);
-            intent.setClass(context, SubscribedFeedsIntentService.class);
+        if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
+            setResultCode(Activity.RESULT_OK);
+        }
+        intent.setClass(context, SubscribedFeedsIntentService.class);
         context.startService(intent);
     }
 }
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 1793587..071a90d 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -721,6 +721,27 @@
 }
 
 
+static int
+android_tts_SynthProxy_stopSync(JNIEnv *env, jobject thiz, jint jniData)
+{
+    int result = TTS_FAILURE;
+
+    if (jniData == 0) {
+        LOGE("android_tts_SynthProxy_stop(): invalid JNI data");
+        return result;
+    }
+
+    // perform a regular stop
+    result = android_tts_SynthProxy_stop(env, thiz, jniData);
+    // but wait on the engine having released the engine mutex which protects
+    // the synthesizer resources.
+    engineMutex.lock();
+    engineMutex.unlock();
+
+    return result;
+}
+
+
 static jobjectArray
 android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
 {
@@ -778,6 +799,10 @@
         "(I)I",
         (void*)android_tts_SynthProxy_stop
     },
+    {   "native_stopSync",
+        "(I)I",
+        (void*)android_tts_SynthProxy_stopSync
+    },
     {   "native_speak",
         "(ILjava/lang/String;I)I",
         (void*)android_tts_SynthProxy_speak
diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java
index a0814aa..1d37ba0 100755
--- a/packages/TtsService/src/android/tts/SynthProxy.java
+++ b/packages/TtsService/src/android/tts/SynthProxy.java
@@ -40,7 +40,7 @@
      * Constructor; pass the location of the native TTS .so to use.
      */
     public SynthProxy(String nativeSoLib) {
-        Log.e("TTS is loading", nativeSoLib);
+        Log.v(TtsService.SERVICE_TAG, "TTS is loading " + nativeSoLib);
         native_setup(new WeakReference<SynthProxy>(this), nativeSoLib);
     }
 
@@ -52,6 +52,18 @@
     }
 
     /**
+     * Synchronous stop of the synthesizer. This method returns when the synth
+     * has completed the stop procedure and doesn't use any of the resources it
+     * was using while synthesizing.
+     *
+     * @return {@link android.speech.tts.TextToSpeech.SUCCESS} or
+     *         {@link android.speech.tts.TextToSpeech.ERROR}
+     */
+    public int stopSync() {
+        return native_stopSync(mJniData);
+    }
+
+    /**
      * Synthesize speech and speak it directly using AudioTrack.
      */
     public int speak(String text, int streamType) {
@@ -156,6 +168,8 @@
 
     private native final int native_stop(int jniData);
 
+    private native final int native_stopSync(int jniData);
+
     private native final int native_speak(int jniData, String text, int streamType);
 
     private native final int native_synthesizeToFile(int jniData, String text, String filename);
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 2e11698..217d3bb 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -122,6 +122,7 @@
     private static final String ACTION = "android.intent.action.START_TTS_SERVICE";
     private static final String CATEGORY = "android.intent.category.TTS";
     private static final String PKGNAME = "android.tts";
+    protected static final String SERVICE_TAG = "TtsService";
 
     private final RemoteCallbackList<ITtsCallback> mCallbacks
             = new RemoteCallbackList<ITtsCallback>();
@@ -188,6 +189,8 @@
 
         // Unregister all callbacks.
         mCallbacks.kill();
+
+        Log.v(SERVICE_TAG, "onDestroy() completed");
     }
 
 
@@ -300,7 +303,7 @@
 
 
     private int setLanguage(String callingApp, String lang, String country, String variant) {
-        Log.v("TtsService", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")");
+        Log.v(SERVICE_TAG, "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")");
         int res = TextToSpeech.ERROR;
         try {
             if (isDefaultEnforced()) {
@@ -384,7 +387,7 @@
      *            engines.
      */
     private int speak(String callingApp, String text, int queueMode, ArrayList<String> params) {
-        Log.v("TtsService", "TTS service received " + text);
+        Log.v(SERVICE_TAG, "TTS service received " + text);
         if (queueMode == TextToSpeech.QUEUE_FLUSH) {
             stop(callingApp);
         } else if (queueMode == 2) {
@@ -433,7 +436,7 @@
             speechQueueAvailable =
                     speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS);
             if (speechQueueAvailable) {
-                Log.i("TtsService", "Stopping");
+                Log.i(SERVICE_TAG, "Stopping");
                 for (int i = mSpeechQueue.size() - 1; i > -1; i--){
                     if (mSpeechQueue.get(i).mCallingApp.equals(callingApp)){
                         mSpeechQueue.remove(i);
@@ -460,13 +463,13 @@
                 } else {
                     result = TextToSpeech.SUCCESS;
                 }
-                Log.i("TtsService", "Stopped");
+                Log.i(SERVICE_TAG, "Stopped");
             } else {
-                Log.e("TtsService", "TTS stop(): queue locked longer than expected");
+                Log.e(SERVICE_TAG, "TTS stop(): queue locked longer than expected");
                 result = TextToSpeech.ERROR;
             }
         } catch (InterruptedException e) {
-          Log.e("TtsService", "TTS stop: tryLock interrupted");
+          Log.e(SERVICE_TAG, "TTS stop: tryLock interrupted");
           e.printStackTrace();
         } finally {
             // This check is needed because finally will always run; even if the
@@ -497,22 +500,21 @@
 
                 // clear the current speech item
                 if (mCurrentSpeechItem != null) {
-                    result = sNativeSynth.stop();
+                    result = sNativeSynth.stopSync();
                     mKillList.put(mCurrentSpeechItem, true);
                     mIsSpeaking = false;
 
                     // was the engine writing to a file?
                     if (mCurrentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) {
                         // delete the file that was being written
-                        // TODO make sure the synth is not writing to the file anymore
                         if (mCurrentSpeechItem.mFilename != null) {
                             File tempFile = new File(mCurrentSpeechItem.mFilename);
-                            Log.v("TtsService", "Leaving behind " + mCurrentSpeechItem.mFilename);
+                            Log.v(SERVICE_TAG, "Leaving behind " + mCurrentSpeechItem.mFilename);
                             if (tempFile.exists()) {
-                                Log.v("TtsService", "About to delete "
+                                Log.v(SERVICE_TAG, "About to delete "
                                         + mCurrentSpeechItem.mFilename);
                                 if (tempFile.delete()) {
-                                    Log.v("TtsService", "file successfully deleted");
+                                    Log.v(SERVICE_TAG, "file successfully deleted");
                                 }
                             }
                         }
@@ -521,11 +523,11 @@
                     mCurrentSpeechItem = null;
                 }
             } else {
-                Log.e("TtsService", "TTS killAllUtterances(): queue locked longer than expected");
+                Log.e(SERVICE_TAG, "TTS killAllUtterances(): queue locked longer than expected");
                 result = TextToSpeech.ERROR;
             }
         } catch (InterruptedException e) {
-            Log.e("TtsService", "TTS killAllUtterances(): tryLock interrupted");
+            Log.e(SERVICE_TAG, "TTS killAllUtterances(): tryLock interrupted");
             result = TextToSpeech.ERROR;
         } finally {
             // This check is needed because finally will always run, even if the
@@ -576,13 +578,13 @@
                 } else {
                     result = TextToSpeech.SUCCESS;
                 }
-                Log.i("TtsService", "Stopped all");
+                Log.i(SERVICE_TAG, "Stopped all");
             } else {
-                Log.e("TtsService", "TTS stopAll(): queue locked longer than expected");
+                Log.e(SERVICE_TAG, "TTS stopAll(): queue locked longer than expected");
                 result = TextToSpeech.ERROR;
             }
         } catch (InterruptedException e) {
-          Log.e("TtsService", "TTS stopAll: tryLock interrupted");
+          Log.e(SERVICE_TAG, "TTS stopAll: tryLock interrupted");
           e.printStackTrace();
         } finally {
             // This check is needed because finally will always run; even if the
@@ -709,11 +711,11 @@
                             sNativeSynth.speak(speechItem.mText, streamType);
                         } catch (NullPointerException e) {
                             // synth will become null during onDestroy()
-                            Log.v("TtsService", " null synth, can't speak");
+                            Log.v(SERVICE_TAG, " null synth, can't speak");
                         }
                     }
                 } catch (InterruptedException e) {
-                    Log.e("TtsService", "TTS speakInternalOnly(): tryLock interrupted");
+                    Log.e(SERVICE_TAG, "TTS speakInternalOnly(): tryLock interrupted");
                     e.printStackTrace();
                 } finally {
                     // This check is needed because finally will always run;
@@ -739,7 +741,7 @@
             public void run() {
                 boolean synthAvailable = false;
                 String utteranceId = "";
-                Log.i("TtsService", "Synthesizing to " + speechItem.mFilename);
+                Log.i(SERVICE_TAG, "Synthesizing to " + speechItem.mFilename);
                 try {
                     synthAvailable = synthesizerLock.tryLock();
                     if (!synthAvailable) {
@@ -783,11 +785,11 @@
                             sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
                         } catch (NullPointerException e) {
                             // synth will become null during onDestroy()
-                            Log.v("TtsService", " null synth, can't synthesize to file");
+                            Log.v(SERVICE_TAG, " null synth, can't synthesize to file");
                         }
                     }
                 } catch (InterruptedException e) {
-                    Log.e("TtsService", "TTS synthToFileInternalOnly(): tryLock interrupted");
+                    Log.e(SERVICE_TAG, "TTS synthToFileInternalOnly(): tryLock interrupted");
                     e.printStackTrace();
                 } finally {
                     // This check is needed because finally will always run;
@@ -832,7 +834,7 @@
         if (cb == null){
             return;
         }
-        Log.v("TtsService", "TTS callback: dispatch started");
+        Log.v(SERVICE_TAG, "TTS callback: dispatch started");
         // Broadcast to all clients the new value.
         final int N = mCallbacks.beginBroadcast();
         try {
@@ -842,7 +844,7 @@
             // the dead object for us.
         }
         mCallbacks.finishBroadcast();
-        Log.v("TtsService", "TTS callback: dispatch completed to " + N);
+        Log.v(SERVICE_TAG, "TTS callback: dispatch completed to " + N);
     }
 
     private SpeechItem splitCurrentTextIfNeeded(SpeechItem currentSpeechItem){
@@ -879,11 +881,12 @@
             speechQueueAvailable =
                     speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS);
             if (!speechQueueAvailable) {
-                Log.e("TtsService", "processSpeechQueue - Speech queue is unavailable.");
+                Log.e(SERVICE_TAG, "processSpeechQueue - Speech queue is unavailable.");
                 return;
             }
             if (mSpeechQueue.size() < 1) {
                 mIsSpeaking = false;
+                mKillList.clear();
                 broadcastTtsQueueProcessingCompleted();
                 return;
             }
@@ -893,7 +896,7 @@
             SoundResource sr = getSoundResource(mCurrentSpeechItem);
             // Synth speech as needed - synthesizer should call
             // processSpeechQueue to continue running the queue
-            Log.v("TtsService", "TTS processing: " + mCurrentSpeechItem.mText);
+            Log.v(SERVICE_TAG, "TTS processing: " + mCurrentSpeechItem.mText);
             if (sr == null) {
                 if (mCurrentSpeechItem.mType == SpeechItem.TEXT) {
                     mCurrentSpeechItem = splitCurrentTextIfNeeded(mCurrentSpeechItem);
@@ -949,7 +952,7 @@
                 mSpeechQueue.remove(0);
             }
         } catch (InterruptedException e) {
-          Log.e("TtsService", "TTS processSpeechQueue: tryLock interrupted");
+          Log.e(SERVICE_TAG, "TTS processSpeechQueue: tryLock interrupted");
           e.printStackTrace();
         } finally {
             // This check is needed because finally will always run; even if the
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 7c33e37..af60556 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -16,12 +16,7 @@
 
 package com.android.server;
 
-import java.io.BufferedReader;
-import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -31,7 +26,6 @@
 import java.util.Observable;
 import java.util.Observer;
 import java.util.Set;
-import java.util.regex.Pattern;
 
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -64,7 +58,6 @@
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
@@ -84,17 +77,9 @@
     private static final String TAG = "LocationManagerService";
     private static final boolean LOCAL_LOGV = false;
 
-    // Minimum time interval between last known location writes, in milliseconds.
-    private static final long MIN_LAST_KNOWN_LOCATION_TIME = 60L * 1000L;
-
-    // Max time to hold wake lock for, in milliseconds.
-    private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L;
-
     // The last time a location was written, by provider name.
     private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
 
-    private static final Pattern PATTERN_COMMA = Pattern.compile(",");
-
     private static final String ACCESS_FINE_LOCATION =
         android.Manifest.permission.ACCESS_FINE_LOCATION;
     private static final String ACCESS_COARSE_LOCATION =
@@ -416,97 +401,6 @@
         }
     }
 
-    private Location readLastKnownLocationLocked(String provider) {
-        Location location = null;
-        String s = null;
-        try {
-            File f = new File(LocationManager.SYSTEM_DIR + "/location."
-                    + provider);
-            if (!f.exists()) {
-                return null;
-            }
-            BufferedReader reader = new BufferedReader(new FileReader(f), 256);
-            s = reader.readLine();
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to read last known location", e);
-        }
-
-        if (s == null) {
-            return null;
-        }
-        try {
-            String[] tokens = PATTERN_COMMA.split(s);
-            int idx = 0;
-            long time = Long.parseLong(tokens[idx++]);
-            double latitude = Double.parseDouble(tokens[idx++]);
-            double longitude = Double.parseDouble(tokens[idx++]);
-            double altitude = Double.parseDouble(tokens[idx++]);
-            float bearing = Float.parseFloat(tokens[idx++]);
-            float speed = Float.parseFloat(tokens[idx++]);
-
-            location = new Location(provider);
-            location.setTime(time);
-            location.setLatitude(latitude);
-            location.setLongitude(longitude);
-            location.setAltitude(altitude);
-            location.setBearing(bearing);
-            location.setSpeed(speed);
-        } catch (NumberFormatException nfe) {
-            Log.e(TAG, "NumberFormatException reading last known location", nfe);
-            return null;
-        }
-
-        return location;
-    }
-
-    private void writeLastKnownLocationLocked(String provider,
-        Location location) {
-        long now = SystemClock.elapsedRealtime();
-        Long last = mLastWriteTime.get(provider);
-        if ((last != null)
-            && (now - last.longValue() < MIN_LAST_KNOWN_LOCATION_TIME)) {
-            return;
-        }
-        mLastWriteTime.put(provider, now);
-
-        StringBuilder sb = new StringBuilder(100);
-        sb.append(location.getTime());
-        sb.append(',');
-        sb.append(location.getLatitude());
-        sb.append(',');
-        sb.append(location.getLongitude());
-        sb.append(',');
-        sb.append(location.getAltitude());
-        sb.append(',');
-        sb.append(location.getBearing());
-        sb.append(',');
-        sb.append(location.getSpeed());
-
-        FileWriter writer = null;
-        try {
-            File d = new File(LocationManager.SYSTEM_DIR);
-            if (!d.exists()) {
-                if (!d.mkdirs()) {
-                    Log.w(TAG, "Unable to create directory to write location");
-                    return;
-                }
-            }
-            File f = new File(LocationManager.SYSTEM_DIR + "/location." + provider);
-            writer = new FileWriter(f);
-            writer.write(sb.toString());
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to write location", e);
-        } finally {
-            if (writer != null) {
-                try {
-                writer.close();
-                } catch (IOException e) {
-                    Log.w(TAG, "Exception closing file", e);
-                }
-            }
-        }
-    }
-
     private void addProvider(LocationProviderProxy provider) {
         mProviders.add(provider);
         mProvidersByName.put(provider.getName(), provider);
@@ -854,7 +748,9 @@
          */
         void disposeLocked() {
             ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider);
-            records.remove(this);
+            if (records != null) {
+                records.remove(this);
+            }
         }
 
         @Override
@@ -873,15 +769,6 @@
             mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
             pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
         }
-        
-        /**
-         * Calls dispose().
-         */
-        @Override protected void finalize() {
-            synchronized (mLock) {
-                disposeLocked();
-            }
-        }
     }
 
     private Receiver getReceiver(ILocationListener listener) {
@@ -1512,16 +1399,7 @@
             return null;
         }
 
-        Location location = mLastKnownLocation.get(provider);
-        if (location == null) {
-            // Get the persistent last known location for the provider
-            location = readLastKnownLocationLocked(provider);
-            if (location != null) {
-                mLastKnownLocation.put(provider, location);
-            }
-        }
-
-        return location;
+        return mLastKnownLocation.get(provider);
     }
 
     private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
@@ -1566,7 +1444,6 @@
         } else {
             lastLocation.set(location);
         }
-        writeLastKnownLocationLocked(provider, location);
 
         // Fetch latest status update time
         long newStatusUpdateTime = p.getStatusUpdateTime();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d4e69c0..867d8a6e 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -68,6 +68,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -4895,6 +4896,25 @@
         Binder.restoreCallingIdentity(origId);
     }
     
+    public void getProcessMemoryInfo(int pid, Debug.MemoryInfo mi)
+            throws RemoteException {
+        ProcessRecord proc;
+        synchronized (mPidsSelfLocked) {
+            proc = mPidsSelfLocked.get(pid);
+        }
+        
+        if (proc == null) {
+            throw new RemoteException();
+        }
+        
+        IApplicationThread thread = proc.thread;
+        if (thread == null) {
+            throw new RemoteException();
+        }
+        
+        thread.getMemoryInfo(mi);
+    }
+    
     private void restartPackageLocked(final String packageName, int uid) {
         uninstallPackageLocked(packageName, uid, false);
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
@@ -9818,6 +9838,7 @@
         if (r.app != null) {
             info.pid = r.app.pid;
         }
+        info.uid = r.appInfo.uid;
         info.process = r.processName;
         info.foreground = r.isForeground;
         info.activeSince = r.createTime;
@@ -9825,6 +9846,18 @@
         info.clientCount = r.connections.size();
         info.crashCount = r.crashCount;
         info.lastActivityTime = r.lastActivity;
+        if (r.isForeground) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
+        }
+        if (r.startRequested) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
+        }
+        if (r.app != null && r.app.pid == Process.myPid()) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
+        }
+        if (r.app != null && r.app.persistent) {
+            info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
+        }
         return info;
     }
     
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 14b1563d..80de074 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -81,9 +81,14 @@
             throw new IllegalArgumentException("Invalid message body");
         }
 
-        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
-                scAddress, destinationAddress, text, (deliveryIntent != null));
-        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                iccISms.sendText(destinationAddress, scAddress, text, sentIntent, deliveryIntent);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
     }
 
     /**
@@ -202,43 +207,11 @@
             throw new IllegalArgumentException("Invalid message data");
         }
 
-        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
-                scAddress, destinationAddress,
-                destinationPort, data, (deliveryIntent != null));
-        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
-    }
-
-    /**
-     * Send a raw SMS PDU.
-     * A PDU is a protocol data unit. It contains the message and the
-     * associated meta information.
-     *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  default SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>PendingIntent</code> is
-     *  broadcast when the message is successfully sent, or failed.
-     *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:<br>
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
-     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
-     *  <code>RESULT_ERROR_NULL_PDU</code><br>
-     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
-     *  the extra "errorCode" containing a radio technology specific value,
-     *  generally only useful for troubleshooting.<br>
-     *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applications,
-     *  which cause smaller number of SMS to be sent in checking period.
-     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
-     *  broadcast when the message is delivered to the recipient.  The
-     *  raw pdu of the status report is in the extended data ("pdu").
-     */
-    private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
         try {
             ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
             if (iccISms != null) {
-                iccISms.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+                iccISms.sendData(destinationAddress, scAddress, destinationPort & 0xFFFF,
+                        data, sentIntent, deliveryIntent);
             }
         } catch (RemoteException ex) {
             // ignore it
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 0617dad..7a10512 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -309,8 +309,13 @@
         while (pos < textLen) {
             int nextPos = 0;  // Counts code units.
             if (ted.codeUnitSize == ENCODING_7BIT) {
-                // For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode).
-                nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit);
+                if (activePhone == PHONE_TYPE_CDMA && ted.msgCount == 1) {
+                    // For a singleton CDMA message, the encoding must be ASCII...
+                    nextPos = pos + Math.min(limit, textLen - pos);
+                } else {
+                    // For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode).
+                    nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit);
+                }
             } else {  // Assume unicode.
                 nextPos = pos + Math.min(limit / 2, textLen - pos);
             }
@@ -345,6 +350,25 @@
         return calculateLength((CharSequence)messageBody, use7bitOnly);
     }
 
+    /*
+     * TODO(cleanup): It looks like there is now no useful reason why
+     * apps should generate pdus themselves using these routines,
+     * instead of handing the raw data to SMSDispatcher (and thereby
+     * have the phone process do the encoding).  Moreover, CDMA now
+     * has shared state (in the form of the msgId system property)
+     * which can only be modified by the phone process, and hence
+     * makes the output of these routines incorrect.  Since they now
+     * serve no purpose, they should probably just return null
+     * directly, and be deprecated.  Going further in that direction,
+     * the above parsers of serialized pdu data should probably also
+     * be gotten rid of, hiding all but the necessarily visible
+     * structured data from client apps.  A possible concern with
+     * doing this is that apps may be using these routines to generate
+     * pdus that are then sent elsewhere, some network server, for
+     * example, and that always returning null would thereby break
+     * otherwise useful apps.
+     */
+
     /**
      * Get an SMS-SUBMIT PDU for a destination address and a message
      *
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 257f1e6..65bad96 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -67,24 +67,56 @@
     boolean copyMessageToIccEf(int status, in byte[] pdu, in byte[] smsc);
 
     /**
-     * Send a SMS
+     * Send a data SMS.
      *
      * @param smsc the SMSC to send the message through, or NULL for the
      *  default SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is successfully sent, or failed.
+     * @param data the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
      *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntent if not NULL this <code>Intent</code> is
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is delivered to the recipient.  The
      *  raw pdu of the status report is in the extended data ("pdu").
      */
-    void sendRawPdu(in byte[] smsc, in byte[] pdu, in PendingIntent sentIntent,
-            in PendingIntent deliveryIntent);
+    void sendData(in String destAddr, in String scAddr, in int destPort,
+            in byte[] data, in PendingIntent sentIntent, in PendingIntent deliveryIntent);
+
+    /**
+     * Send an SMS.
+     *
+     * @param smsc the SMSC to send the message through, or NULL for the
+     *  default SMSC
+     * @param text the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    void sendText(in String destAddr, in String scAddr, in String text,
+            in PendingIntent sentIntent, in PendingIntent deliveryIntent);
 
     /**
      * Send a multi-part text based SMS.
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 620f2de..2cb0041 100644
--- a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -20,6 +20,8 @@
 import android.content.Context;
 import android.util.Log;
 
+import com.android.internal.util.HexDump;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -49,40 +51,81 @@
     }
 
     /**
-     * Send a Raw PDU SMS
+     * Send a data based SMS to a specific application port.
      *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  defatult SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>Intent</code> is
+     * @param destAddr the address to send the message to
+     * @param scAddr is the service center address or null to use
+     *  the current default SMSC
+     * @param destPort the port to deliver the message to
+     * @param data the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is sucessfully sent, or failed.
      *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntent if not NULL this <code>Intent</code> is
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is delivered to the recipient.  The
      *  raw pdu of the status report is in the extended data ("pdu").
      */
-    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        Context context = mPhone.getContext();
-
-        context.enforceCallingPermission(
+    public void sendData(String destAddr, String scAddr, int destPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        mPhone.getContext().enforceCallingPermission(
                 "android.permission.SEND_SMS",
                 "Sending SMS message");
-        if (DBG) log("sendRawPdu: smsc=" + smsc +
-                " pdu="+ pdu + " sentIntent" + sentIntent +
-                " deliveryIntent" + deliveryIntent);
-        mDispatcher.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+        if (DBG) log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort=" +
+                destPort + " data='"+ HexDump.toHexString(data)  + "' sentIntent=" +
+                sentIntent + " deliveryIntent=" + deliveryIntent);
+        mDispatcher.sendData(destAddr, scAddr, destPort, data, sentIntent, deliveryIntent);
+    }
+
+    /**
+     * Send a text based SMS.
+     *
+     * @param destAddr the address to send the message to
+     * @param scAddr is the service center address or null to use
+     *  the current default SMSC
+     * @param text the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    public void sendText(String destAddr, String scAddr,
+            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        mPhone.getContext().enforceCallingPermission(
+                "android.permission.SEND_SMS",
+                "Sending SMS message");
+        if (DBG) log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
+                " text='"+ text + "' sentIntent=" +
+                sentIntent + " deliveryIntent=" + deliveryIntent);
+        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
     }
 
     /**
      * Send a multi-part text based SMS.
      *
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
+     * @param destAddr the address to send the message to
+     * @param scAddr is the service center address or null to use
      *   the current default SMSC
      * @param parts an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
@@ -94,21 +137,22 @@
      *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
      *   <code>RESULT_ERROR_RADIO_OFF</code>
      *   <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
      * @param deliveryIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been delivered
      *   to the recipient.  The raw pdu of the status report is in the
      *   extended data ("pdu").
      */
-    public void sendMultipartText(String destinationAddress, String scAddress, List<String> parts,
+    public void sendMultipartText(String destAddr, String scAddr, List<String> parts,
             List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
-        Context context = mPhone.getContext();
-
-        context.enforceCallingPermission(
+        mPhone.getContext().enforceCallingPermission(
                 "android.permission.SEND_SMS",
                 "Sending SMS message");
         if (DBG) log("sendMultipartText");
-        mDispatcher.sendMultipartText(destinationAddress, scAddress, (ArrayList<String>) parts,
+        mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
                 (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
     }
 
@@ -163,4 +207,3 @@
     protected abstract void log(String msg);
 
 }
-
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
index a51d074..1910a9c 100644
--- a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
@@ -50,16 +50,21 @@
         return mIccSmsInterfaceManager.getAllMessagesFromIccEf();
     }
 
-    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) throws android.os.RemoteException {
-        mIccSmsInterfaceManager.sendRawPdu(smsc, pdu, sentIntent,
-                deliveryIntent);
+    public void sendData(String destAddr, String scAddr, int destPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        mIccSmsInterfaceManager.sendData(destAddr, scAddr, destPort, data,
+                sentIntent, deliveryIntent);
     }
 
-    public void sendMultipartText(String destinationAddress, String scAddress,
+    public void sendText(String destAddr, String scAddr,
+            String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        mIccSmsInterfaceManager.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
+    }
+
+    public void sendMultipartText(String destAddr, String scAddr,
             List<String> parts, List<PendingIntent> sentIntents,
             List<PendingIntent> deliveryIntents) throws android.os.RemoteException {
-        mIccSmsInterfaceManager.sendMultipartText(destinationAddress, scAddress,
+        mIccSmsInterfaceManager.sendMultipartText(destAddr, scAddr,
                 parts, sentIntents, deliveryIntents);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index bbfc6c9..7efaa2e 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -635,12 +635,66 @@
         dispatch(intent, "android.permission.RECEIVE_SMS");
     }
 
+    /**
+     * Send a data based SMS to a specific application port.
+     *
+     * @param destAddr the address to send the message to
+     * @param scAddr is the service center address or null to use
+     *  the current default SMSC
+     * @param destPort the port to deliver the message to
+     * @param data the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    protected abstract void sendData(String destAddr, String scAddr, int destPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent);
+
+    /**
+     * Send a text based SMS.
+     *
+     * @param destAddr the address to send the message to
+     * @param scAddr is the service center address or null to use
+     *  the current default SMSC
+     * @param text the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:<br>
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
+     *  <code>RESULT_ERROR_RADIO_OFF</code><br>
+     *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
+     *  the extra "errorCode" containing a radio technology specific value,
+     *  generally only useful for troubleshooting.<br>
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    protected abstract void sendText(String destAddr, String scAddr,
+            String text, PendingIntent sentIntent, PendingIntent deliveryIntent);
 
     /**
      * Send a multi-part text based SMS.
      *
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
+     * @param destAddr the address to send the message to
+     * @param scAddr is the service center address or null to use
      *   the current default SMSC
      * @param parts an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
@@ -661,7 +715,7 @@
      *   to the recipient.  The raw pdu of the status report is in the
      *   extended data ("pdu").
      */
-    protected abstract void sendMultipartText(String destinationAddress, String scAddress,
+    protected abstract void sendMultipartText(String destAddr, String scAddr,
             ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
             ArrayList<PendingIntent> deliveryIntents);
 
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index c74bb8d..cc13450 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -28,20 +28,9 @@
  * {@hide}
  */
 public abstract class ServiceStateTracker extends Handler {
+
     /**
-     *  The access technology currently in use:
-     *  0 = unknown
-     *  1 = GPRS only
-     *  2 = EDGE
-     *  3 = UMTS
-     *  4 = IS95A
-     *  5 = IS95B
-     *  6 = 1xRTT
-     *  7 = EvDo_0
-     *  8 = EvDo_A
-     *  9 = HSDPA
-     *  10 = HSUPA
-     *  11 = HSPA
+     *  Access technology currently in use.
      */
     protected static final int DATA_ACCESS_UNKNOWN = 0;
     protected static final int DATA_ACCESS_GPRS = 1;
@@ -55,7 +44,6 @@
     protected static final int DATA_ACCESS_HSDPA = 9;
     protected static final int DATA_ACCESS_HSUPA = 10;
     protected static final int DATA_ACCESS_HSPA = 11;
-    //***** Instance Variables
 
     protected CommandsInterface cm;
 
@@ -64,33 +52,36 @@
 
     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
+    /**
+     * A unique identifier to track requests associated with a poll
+     * and ignore stale responses.  The value is a count-down of
+     * expected responses in this pollingContext.
+     */
     protected int[] pollingContext;
     protected boolean mDesiredPowerState;
 
-    protected boolean dontPollSignalStrength = false; // Default is to poll strength
-    // If we're getting unsolicited signal strength updates from the radio,
-    // set value to true and don't bother polling any more
+    /**
+     * By default, strength polling is enabled.  However, if we're
+     * getting unsolicited signal strength updates from the radio, set
+     * value to true and don't bother polling any more.
+     */
+    protected boolean dontPollSignalStrength = false;
 
     protected RegistrantList networkAttachedRegistrants = new RegistrantList();
     protected RegistrantList roamingOnRegistrants = new RegistrantList();
     protected RegistrantList roamingOffRegistrants = new RegistrantList();
 
-    //***** Constants
-
     protected  static final boolean DBG = true;
 
-    // signal strength poll rate
+    /** Signal strength poll rate. */
     protected static final int POLL_PERIOD_MILLIS = 20 * 1000;
 
-    // waiting period before recheck gprs and voice registration
+    /** Waiting period before recheck gprs and voice registration. */
     public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
 
     public static final int DATA_STATE_POLL_SLEEP_MS = 100;
 
-    //*****GSM events
+    /** GSM events */
     protected static final int EVENT_RADIO_STATE_CHANGED               = 1;
     protected static final int EVENT_NETWORK_STATE_CHANGED             = 2;
     protected static final int EVENT_GET_SIGNAL_STRENGTH               = 3;
@@ -112,7 +103,7 @@
     protected static final int EVENT_CHECK_REPORT_GPRS                 = 22;
     protected static final int EVENT_RESTRICTED_STATE_CHANGED          = 23;
 
-    //*****CDMA events:
+    /** CDMA events */
     protected static final int EVENT_POLL_STATE_REGISTRATION_CDMA      = 24;
     protected static final int EVENT_POLL_STATE_OPERATOR_CDMA          = 25;
     protected static final int EVENT_RUIM_READY                        = 26;
@@ -129,13 +120,14 @@
     protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE       = 37;
     protected static final int EVENT_SET_RADIO_POWER_OFF               = 38;
 
-    //***** Time Zones
     protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
 
-    // List of ISO codes for countries that can have an offset of GMT+0
-    // when not in daylight savings time.  This ignores some small places
-    // such as the Canary Islands (Spain) and Danmarkshavn (Denmark).
-    // The list must be sorted by code.
+    /**
+     * List of ISO codes for countries that can have an offset of
+     * GMT+0 when not in daylight savings time.  This ignores some
+     * small places such as the Canary Islands (Spain) and
+     * Danmarkshavn (Denmark).  The list must be sorted by code.
+    */
     protected static final String[] GMT_COUNTRY_CODES = {
         "bf", // Burkina Faso
         "ci", // Cote d'Ivoire
@@ -159,11 +151,10 @@
         "uk", // U.K
     };
 
-    //***** Registration denied reason
+    /** Reason for registration denial. */
     protected static final String REGISTRATION_DENIED_GEN  = "General";
     protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
 
-    //***** Constructors
     public ServiceStateTracker() {
 
     }
@@ -228,8 +219,6 @@
                 obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
     }
 
-
-    //***** Called from Phone
     public void
     setRadioPower(boolean power) {
         mDesiredPowerState = power;
@@ -237,7 +226,6 @@
         setPowerStateToDesired();
     }
 
-
     public void enableLocationUpdates() {
         cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
     }
@@ -246,17 +234,15 @@
         cm.setLocationUpdates(false, null);
     }
 
-    //***** Overridden from Handler
     public abstract void handleMessage(Message msg);
 
-    //***** Protected abstract Methods
     protected abstract void handlePollStateResult(int what, AsyncResult ar);
     protected abstract void updateSpnDisplay();
     protected abstract void setPowerStateToDesired();
 
     /** Cancel a pending (if any) pollState() operation */
     protected void cancelPollState() {
-        // This will effectively cancel the rest of the poll requests
+        // This will effectively cancel the rest of the poll requests.
         pollingContext = new int[1];
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 6177c8a..e73039b 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -116,6 +116,16 @@
          * android.telephony.SmsMessage ENCODING_*).
          */
         public int codeUnitSize;
+
+        @Override
+        public String toString() {
+            return "TextEncodingDetails " +
+                    "{ msgCount=" + msgCount +
+                    ", codeUnitCount=" + codeUnitCount +
+                    ", codeUnitsRemaining=" + codeUnitsRemaining +
+                    ", codeUnitSize=" + codeUnitSize +
+                    " }";
+        }
     }
 
     // TODO(): This class is duplicated in SmsMessage.java. Refactor accordingly.
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index de5bbc1..55ba149 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -130,4 +130,10 @@
      * The number of milli-seconds between CALL_RING notifications.
      */
     static final String PROPERTY_CALL_RING_DELAY = "ro.telephony.call_ring.delay";
+
+    /**
+     * Track CDMA SMS message id numbers to ensure they increment
+     * monotonically, regardless of reboots.
+     */
+    static final String PROPERTY_CDMA_MSG_ID = "persist.radio.cdma.msgid";
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 88cccd3..ca15a03 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -286,6 +286,22 @@
     }
 
     /** {@inheritDoc} */
+    protected void sendData(String destAddr, String scAddr, int destPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
+                scAddr, destAddr, destPort, data, (deliveryIntent != null));
+        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
+    }
+
+    /** {@inheritDoc} */
+    protected void sendText(String destAddr, String scAddr, String text,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
+                scAddr, destAddr, text, (deliveryIntent != null), null);
+        sendSubmitPdu(pdu, sentIntent, deliveryIntent);
+    }
+
+    /** {@inheritDoc} */
     protected void sendMultipartText(String destAddr, String scAddr,
             ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
             ArrayList<PendingIntent> deliveryIntents) {
@@ -329,16 +345,9 @@
         }
     }
 
-    protected void sendSubmitPdu(SmsMessage.SubmitPdu submitPdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        sendRawPdu(submitPdu.encodedScAddress, submitPdu.encodedMessage,
-                sentIntent, deliveryIntent);
-    }
-
-    protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);
-        if (Boolean.parseBoolean(inEcm)) {
+    protected void sendSubmitPdu(SmsMessage.SubmitPdu pdu,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        if (SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false)) {
             if (sentIntent != null) {
                 try {
                     sentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
@@ -349,8 +358,7 @@
             }
             return;
         }
-
-        super.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+        sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
     }
 
     /** {@inheritDoc} */
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index b4de09b..4c958f6 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -41,28 +41,19 @@
 import android.util.Log;
 import android.util.Config;
 import android.util.TimeUtils;
-import java.util.Calendar;
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DataConnectionTracker;
-// pretty sure importing stuff from GSM is bad:
 import com.android.internal.telephony.gsm.MccTable;
 import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyEventLog;
 import com.android.internal.telephony.TelephonyIntents;
-
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISMANUAL;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+import com.android.internal.telephony.TelephonyProperties;
 
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 
@@ -70,14 +61,14 @@
  * {@hide}
  */
 final class CdmaServiceStateTracker extends ServiceStateTracker {
+    static final String LOG_TAG = "CDMA";
 
-    //***** Instance Variables
     CDMAPhone phone;
     CdmaCellLocation cellLoc;
     CdmaCellLocation newCellLoc;
 
     /**
-     *  The access technology currently in use: DATA_ACCESS_
+     *  Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
      */
     private int networkType = 0;
     private int newNetworkType = 0;
@@ -87,7 +78,9 @@
     private boolean mIsInPrl;
     private int mDefaultRoamingIndicator;
 
-    // Initially we assume no data connection
+    /**
+     * Initially assume no data connection.
+     */
     private int cdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
     private int newCdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
     private int mRegistrationState = -1;
@@ -95,9 +88,11 @@
     private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
     private RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
 
-    // Sometimes we get the NITZ time before we know what country we are in.
-    // Keep the time zone information from the NITZ string so we can fix
-    // the time zone once know the country.
+    /**
+     * Sometimes we get the NITZ time before we know what country we
+     * are in. Keep the time zone information from the NITZ string so
+     * we can fix the time zone once know the country.
+     */
     private boolean mNeedFixZone = false;
     private int mZoneOffset;
     private boolean mZoneDst;
@@ -107,20 +102,23 @@
     long mSavedTime;
     long mSavedAtTime;
 
-    // We can't register for SIM_RECORDS_LOADED immediately because the
-    // SIMRecords object may not be instantiated yet.
+    /**
+     * We can't register for SIM_RECORDS_LOADED immediately because the
+     * SIMRecords object may not be instantiated yet.
+     */
     private boolean mNeedToRegForRuimLoaded = false;
 
-    // Wake lock used while setting time of day.
+    /** Wake lock used while setting time of day. */
     private PowerManager.WakeLock mWakeLock;
     private static final String WAKELOCK_TAG = "ServiceStateTracker";
 
-    // Keep track of SPN display rules, so we only broadcast intent if something changes.
+    /** Track of SPN display rules, so we only broadcast intent if something changes. */
     private String curSpn = null;
-    private String curPlmn = null; // it contains the name of the registered network in CDMA can
-                                   // be the ONS or ERI text
     private int curSpnRule = 0;
 
+    /** Contains the name of the registered network in CDMA (either ONS or ERI text). */
+    private String curPlmn = null;
+
     private String mMdn;
     private int mHomeSystemId[] = null;
     private int mHomeNetworkId[] = null;
@@ -133,12 +131,9 @@
 
     private boolean mPendingRadioPowerOffAfterDataOff = false;
 
-    // Registration Denied Reason, General/Authentication Failure, used only for debugging purposes
+    /* Used only for debugging purposes. */
     private String mRegistrationDeniedReason;
 
-    //***** Constants
-    static final String LOG_TAG = "CDMA";
-
     private ContentResolver cr;
     private String currentCarrier = null;
 
@@ -151,9 +146,6 @@
         }
     };
 
-
-    //***** Constructors
-
     public CdmaServiceStateTracker(CDMAPhone phone) {
         super();
 
@@ -182,7 +174,7 @@
         phone.registerForEriFileLoaded(this, EVENT_ERI_FILE_LOADED, null);
         cm.registerForCdmaOtaProvision(this,EVENT_OTA_PROVISION_STATUS_CHANGE, null);
 
-        // system setting property AIRPLANE_MODE_ON is set in Settings.
+        // System setting property AIRPLANE_MODE_ON is set in Settings.
         int airplaneMode = Settings.System.getInt(
                 phone.getContext().getContentResolver(),
                 Settings.System.AIRPLANE_MODE_ON, 0);
@@ -198,7 +190,7 @@
     }
 
     public void dispose() {
-        //Unregister for all events
+        // Unregister for all events.
         cm.unregisterForAvailable(this);
         cm.unregisterForRadioStateChanged(this);
         cm.unregisterForNetworkStateChanged(this);
@@ -236,8 +228,7 @@
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    /*protected*/ void
-    registerForCdmaDataConnectionAttached(Handler h, int what, Object obj) {
+    void registerForCdmaDataConnectionAttached(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         cdmaDataConnectionAttachedRegistrants.add(r);
 
@@ -245,6 +236,7 @@
             r.notifyRegistrant();
         }
     }
+
     void unregisterForCdmaDataConnectionAttached(Handler h) {
         cdmaDataConnectionAttachedRegistrants.remove(h);
     }
@@ -255,8 +247,7 @@
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    /*protected*/  void
-    registerForCdmaDataConnectionDetached(Handler h, int what, Object obj) {
+    void registerForCdmaDataConnectionDetached(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         cdmaDataConnectionDetachedRegistrants.add(r);
 
@@ -264,6 +255,7 @@
             r.notifyRegistrant();
         }
     }
+
     void unregisterForCdmaDataConnectionDetached(Handler h) {
         cdmaDataConnectionDetachedRegistrants.remove(h);
     }
@@ -287,7 +279,6 @@
         cdmaForSubscriptionInfoReadyRegistrants.remove(h);
     }
 
-    //***** Called from CDMAPhone
     public void
     getLacAndCid(Message onComplete) {
         cm.getRegistrationState(obtainMessage(
@@ -302,14 +293,11 @@
 
         switch (msg.what) {
         case EVENT_RADIO_AVAILABLE:
-            //this is unnecessary
-            //setPowerStateToDesired();
             break;
 
         case EVENT_RUIM_READY:
-            // The RUIM is now ready i.e if it was locked
-            // it has been unlocked. At this stage, the radio is already
-            // powered on.
+            // 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,
@@ -320,10 +308,10 @@
             cm.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
             if (DBG) log("Receive EVENT_RUIM_READY and Send Request getCDMASubscription.");
 
-            // restore the previous network selection.
+            // Restore the previous network selection.
             pollState();
 
-            // Signal strength polling stops when radio is off
+            // Signal strength polling stops when radio is off.
             queueNextSignalStrengthPoll();
             break;
 
@@ -334,13 +322,12 @@
             // subscription info.
             cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
             pollState();
-            // Signal strength polling stops when radio is off
+            // Signal strength polling stops when radio is off.
             queueNextSignalStrengthPoll();
             break;
 
         case EVENT_RADIO_STATE_CHANGED:
-            // This will do nothing in the radio not
-            // available case
+            // This will do nothing in the 'radio not available' case.
             setPowerStateToDesired();
             pollState();
             break;
@@ -351,10 +338,10 @@
 
         case EVENT_GET_SIGNAL_STRENGTH:
             // This callback is called when signal strength is polled
-            // all by itself
+            // all by itself.
 
             if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isGsm())) {
-                // Polling will continue when radio turns back on
+                // Polling will continue when radio turns back on.
                 return;
             }
             ar = (AsyncResult) msg.obj;
@@ -390,7 +377,7 @@
                     }
                 }
 
-                // only update if cell location really changed
+                // Only update if cell location really changed.
                 if (cellLoc.getBaseStationId() != baseStationData[0]
                         || cellLoc.getBaseStationLatitude() != baseStationData[1]
                         || cellLoc.getBaseStationLongitude() != baseStationData[2]) {
@@ -479,13 +466,12 @@
             break;
 
         case EVENT_SIGNAL_STRENGTH_UPDATE:
-            // This is a notification from
-            // CommandsInterface.setOnSignalStrengthUpdate
+            // This is a notification from CommandsInterface.setOnSignalStrengthUpdate.
 
             ar = (AsyncResult) msg.obj;
 
-            // The radio is telling us about signal strength changes
-            // we don't have to ask it
+            // The radio is telling us about signal strength changes,
+            // so we don't have to ask it.
             dontPollSignalStrength = true;
 
             onSignalStrengthResult(ar);
@@ -504,7 +490,7 @@
             break;
 
         case EVENT_ERI_FILE_LOADED:
-            // Repoll the state once the ERI file has been loaded
+            // Repoll the state once the ERI file has been loaded.
             if (DBG) log("[CdmaServiceStateTracker] ERI file has been loaded, repolling.");
             pollState();
             break;
@@ -627,7 +613,7 @@
         int ints[];
         String states[];
 
-        // Ignore stale requests from last poll
+        // Ignore stale requests from last poll.
         if (ar.userObj != pollingContext) return;
 
         if (ar.exception != null) {
@@ -638,13 +624,13 @@
             }
 
             if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
-                // Radio has crashed or turned off
+                // Radio has crashed or turned off.
                 cancelPollState();
                 return;
             }
 
             if (!cm.getRadioState().isOn()) {
-                // Radio has crashed or turned off
+                // Radio has crashed or turned off.
                 cancelPollState();
                 return;
             }
@@ -698,13 +684,15 @@
                 }
 
                 mRegistrationState = registrationState;
-                // mCdmaRoaming is true when registration state is roaming and TSB58 roaming
-                // indicator is not in the carrier-specified list of ERIs for home system
+                // When registration state is roaming and TSB58
+                // roaming indicator is not in the carrier-specified
+                // list of ERIs for home system, mCdmaRoaming is true.
                 mCdmaRoaming =
                         regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
                 newSS.setState (regCodeToServiceState(registrationState));
 
-                this.newCdmaDataConnectionState = radioTechnologyToDataServiceState(radioTechnology);
+                this.newCdmaDataConnectionState =
+                        radioTechnologyToDataServiceState(radioTechnology);
                 newSS.setRadioTechnology(radioTechnology);
                 newNetworkType = radioTechnology;
 
@@ -715,7 +703,7 @@
                 mDefaultRoamingIndicator = defaultRoamingIndicator;
 
 
-                // values are -1 if not available
+                // Values are -1 if not available.
                 newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
                         baseStationLongitude, systemId, networkId);
 
@@ -737,8 +725,8 @@
 
                 if (opNames != null && opNames.length >= 3) {
                     if (cm.getRadioState().isNVReady()) {
-                        // In CDMA in case on NV the ss.mOperatorAlphaLong is set later with the
-                        // ERI text, so here it is ignored what is coming from the modem
+                        // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
+                        // ERI text, so here it is ignored what is coming from the modem.
                         newSS.setOperatorName(null, opNames[1], opNames[2]);
                     } else {
                         newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
@@ -803,9 +791,8 @@
                 }
             }
 
-
-            // NOTE: Some operator may require to override the mCdmaRoaming (set by the modem)
-            // depending on the mRoamingIndicator.
+            // NOTE: Some operator may require overriding mCdmaRoaming
+            // (set by the modem), depending on the mRoamingIndicator.
 
             if (DBG) {
                 log("Set CDMA Roaming Indicator to: " + newSS.getCdmaRoamingIndicator()
@@ -865,13 +852,13 @@
             setSignalStrengthDefaultValues();
             mGotCountryCode = false;
 
-            //NOTE: pollStateDone() is not needed in this case
+            // NOTE: pollStateDone() is not needed in this case
             break;
 
         default:
-            // Issue all poll-related commands at once
-            // then count down the responses, which
-            // are allowed to arrive out-of-order
+            // Issue all poll-related commands at once, then count
+            // down the responses which are allowed to arrive
+            // out-of-order.
 
             pollingContext[0]++;
             // RIL_REQUEST_OPERATOR is necessary for CDMA
@@ -1000,7 +987,7 @@
         newSS.setStateOutOfService(); // clean slate for next time
 
         if (hasNetworkTypeChanged) {
-            phone.setSystemProperty(PROPERTY_DATA_NETWORK_TYPE,
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
                     networkTypeToString(networkType));
         }
 
@@ -1027,14 +1014,14 @@
 
             String operatorNumeric;
 
-            phone.setSystemProperty(PROPERTY_OPERATOR_ALPHA,
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
                     ss.getOperatorAlphaLong());
 
             operatorNumeric = ss.getOperatorNumeric();
-            phone.setSystemProperty(PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
 
             if (operatorNumeric == null) {
-                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, "");
+                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
             } else {
                 String isoCountryCode = "";
                 try{
@@ -1046,14 +1033,15 @@
                     Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
                 }
 
-                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, isoCountryCode);
+                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
+                        isoCountryCode);
                 mGotCountryCode = true;
                 if (mNeedFixZone) {
                     fixTimeZone(isoCountryCode);
                 }
             }
 
-            phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
                     ss.getRoaming() ? "true" : "false");
 
             updateSpnDisplay();
@@ -1282,7 +1270,7 @@
      */
     private
     boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) {
-        String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
+        String spn = SystemProperties.get(TelephonyProperties.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)
@@ -1366,7 +1354,7 @@
                 zone = TimeZone.getTimeZone( tzname );
             }
 
-            String iso = SystemProperties.get(PROPERTY_OPERATOR_ISO_COUNTRY);
+            String iso = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY);
 
             if (zone == null) {
 
@@ -1549,7 +1537,6 @@
      * that could support voice and data simultaneously.
      */
     boolean isConcurrentVoiceAndData() {
-
         // Note: it needs to be confirmed which CDMA network types
         // can support voice and data calls concurrently.
         // For the time-being, the return value will be false.
@@ -1576,11 +1563,12 @@
     /**
      * Returns IMSI as MCC + MNC + MIN
      */
-    /*package*/ String getImsi() {
+    String getImsi() {
         // TODO(Moto): When RUIM is enabled, IMSI will come from RUIM
         // not build-time props. Moto will provide implementation
         // for RUIM-ready case later.
-        String operatorNumeric = SystemProperties.get(PROPERTY_ICC_OPERATOR_NUMERIC, "");
+        String operatorNumeric = SystemProperties.get(
+                TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
 
         if (!TextUtils.isEmpty(operatorNumeric) && getCdmaMin() != null) {
             return (operatorNumeric + getCdmaMin());
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 1597427..2c20784 100755
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony.cdma;
 
 import android.os.Parcel;
+import android.os.SystemProperties;
 import android.text.format.Time;
 import android.util.Config;
 import android.util.Log;
@@ -25,6 +26,7 @@
 import com.android.internal.telephony.IccUtils;
 import com.android.internal.telephony.SmsHeader;
 import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.cdma.sms.BearerData;
 import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
 import com.android.internal.telephony.cdma.sms.SmsEnvelope;
@@ -38,7 +40,6 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
-import java.util.Random;
 
 /**
  * TODO(cleanup): these constants are disturbing... are they not just
@@ -78,14 +79,6 @@
      */
     private int status;
 
-    /** The next message ID for the BearerData. Shall be a random value on first use.
-     * (See C.S0015-B, v2.0, 4.3.1.5)
-     */
-    private static int nextMessageId = 0;
-
-    /** Specifies if this is the first SMS message submit */
-    private static boolean firstSMS = true;
-
     /** Specifies if a return of an acknowledgment is requested for send SMS */
     private static final int RETURN_NO_ACK  = 0;
     private static final int RETURN_ACK     = 1;
@@ -331,7 +324,7 @@
      *         address, if applicable, and the encoded message.
      *         Returns null on encode error.
      */
-    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, short destPort,
+    public static SubmitPdu getSubmitPdu(String scAddr, String destAddr, int destPort,
             byte[] data, boolean statusReportRequested) {
 
         /**
@@ -605,18 +598,28 @@
     }
 
     /**
-     * Set the nextMessageId to a random value between 0 and 65536
-     * See C.S0015-B, v2.0, 4.3.1.5
+     * Calculate the next message id, starting at 0 and iteratively
+     * incrementing within the range 0..65535 remembering the state
+     * via a persistent system property.  (See C.S0015-B, v2.0,
+     * 4.3.1.5)
      */
-    private static void setNextMessageId() {
-        // Message ID, modulo 65536
-        if(firstSMS) {
-            Random generator = new Random();
-            nextMessageId = generator.nextInt(65536);
-            firstSMS = false;
-        } else {
-            nextMessageId = ++nextMessageId & 0xFFFF;
+    private synchronized static int getNextMessageId() {
+        // The only (meaningful) way this code can be called is via
+        // binder-call into the Phone process.  All other calls will
+        // assumedly not be as with UID radio, and hence will be
+        // unable to modify the system property.  Synchronization has
+        // thus been added to this function conservatively -- if it
+        // can be conclusively reasoned to be unnecessary, it should
+        // be removed.
+        int msgId = SystemProperties.getInt(TelephonyProperties.PROPERTY_CDMA_MSG_ID, 0);
+        String nextMsgId = Integer.toString((msgId + 1) & 0xFFFF);
+        SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId);
+        if (DBG_SMS) {
+            Log.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId);
+            Log.d(LOG_TAG, "readback gets " +
+                    SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID));
         }
+        return msgId;
     }
 
     /**
@@ -642,8 +645,7 @@
         BearerData bearerData = new BearerData();
         bearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
 
-        if (userData != null) setNextMessageId();
-        bearerData.messageId = nextMessageId;
+        bearerData.messageId = getNextMessageId();
 
         bearerData.deliveryAckReq = statusReportRequested;
         bearerData.userAckReq = false;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 2770ddc..b412fec 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -137,6 +137,22 @@
     }
 
     /** {@inheritDoc} */
+    protected void sendData(String destAddr, String scAddr, int destPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
+                scAddr, destAddr, destPort, data, (deliveryIntent != null));
+        sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
+    }
+
+    /** {@inheritDoc} */
+    protected void sendText(String destAddr, String scAddr, String text,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
+                scAddr, destAddr, text, (deliveryIntent != null));
+        sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
+    }
+
+    /** {@inheritDoc} */
     protected void sendMultipartText(String destinationAddress, String scAddress,
             ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
             ArrayList<PendingIntent> deliveryIntents) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index e7406e2..a9be068 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,13 +16,6 @@
 
 package com.android.internal.telephony.gsm;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -60,6 +53,7 @@
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyEventLog;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
 
 import java.util.Arrays;
 import java.util.Calendar;
@@ -70,8 +64,9 @@
  * {@hide}
  */
 final class GsmServiceStateTracker extends ServiceStateTracker {
+    static final String LOG_TAG = "GSM";
+    static final boolean DBG = true;
 
-    //***** Instance Variables
     GSMPhone phone;
     GsmCellLocation cellLoc;
     GsmCellLocation newCellLoc;
@@ -82,13 +77,15 @@
     private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
 
     /**
-     *  The access technology currently in use: DATA_ACCESS_
+     *  Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
      */
     private int networkType = 0;
     private int newNetworkType = 0;
-    /* gsm roaming status solely based on TS 27.007 7.2 CREG */
+
+    /** GSM roaming status solely based on TS 27.007 7.2 CREG. */
     private boolean mGsmRoaming = false;
-    /* data roaming status solely based on TS 27.007 10.1.19 CGREG */
+
+    /** Data roaming status solely based on TS 27.007 10.1.19 CGREG. */
     private boolean mDataRoaming = false;
     private boolean newDataRoaming = false;
 
@@ -97,9 +94,11 @@
     private RegistrantList psRestrictEnabledRegistrants = new RegistrantList();
     private RegistrantList psRestrictDisabledRegistrants = new RegistrantList();
 
-    // Sometimes we get the NITZ time before we know what country we are in.
-    // Keep the time zone information from the NITZ string so we can fix
-    // the time zone once know the country.
+    /**
+     * Sometimes we get the NITZ time before we know what country we
+     * are in. Keep the time zone information from the NITZ string so
+     * we can fix the time zone once know the country.
+     */
     private boolean mNeedFixZone = false;
     private int mZoneOffset;
     private boolean mZoneDst;
@@ -111,13 +110,16 @@
     long mSavedTime;
     long mSavedAtTime;
 
-    // We can't register for SIM_RECORDS_LOADED immediately because the
-    // SIMRecords object may not be instantiated yet.
+    /**
+     * We can't register for SIM_RECORDS_LOADED immediately because the
+     * SIMRecords object may not be instantiated yet.
+     */
     private boolean mNeedToRegForSimLoaded;
 
-    // Started the recheck process after finding gprs should registerd but not
+    /** Started the recheck process after finding gprs should registerd but not. */
     private boolean mStartedGprsRegCheck = false;
-    // Already sent the event-log for no gprs register
+
+    /** Already sent the event-log for no gprs register. */
     private boolean mReportedGprsNoReg = false;
 
     /**
@@ -125,34 +127,29 @@
      */
     private Notification mNotification;
 
-    // Wake lock used while setting time of day.
+    /** Wake lock used while setting time of day. */
     private PowerManager.WakeLock mWakeLock;
     private static final String WAKELOCK_TAG = "ServiceStateTracker";
 
-    // Keep track of SPN display rules, so we only broadcast intent if something changes.
+    /** Keep track of SPN display rules, so we only broadcast intent if something changes. */
     private String curSpn = null;
     private String curPlmn = null;
     private int curSpnRule = 0;
 
-    //***** Constants
-
-    static final boolean DBG = true;
-    static final String LOG_TAG = "GSM";
-
-    // waiting period before recheck gprs and voice registration
+    /** waiting period before recheck gprs and voice registration. */
     static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
 
-    // notification type
-    static final int PS_ENABLED = 1001;             // Access Control blocks data service
-    static final int PS_DISABLED = 1002;            // Access Control enables data service
-    static final int CS_ENABLED = 1003;             // Access Control blocks all voice/sms service
-    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 type. */
+    static final int PS_ENABLED = 1001;            // Access Control blocks data service
+    static final int PS_DISABLED = 1002;           // Access Control enables data service
+    static final int CS_ENABLED = 1003;            // Access Control blocks all voice/sms service
+    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 CS_NOTIFICATION = 999; //id to update and cancel CS restricted
+    /** Notification id. */
+    static final int PS_NOTIFICATION = 888;  // Id to update and cancel PS restricted
+    static final int CS_NOTIFICATION = 999;  // Id to update and cancel CS restricted
 
     static final int MAX_NUM_DATA_STATE_READS = 15;
 
@@ -164,9 +161,6 @@
         }
     };
 
-
-    //***** Constructors
-
     public GsmServiceStateTracker(GSMPhone phone) {
         super();
 
@@ -207,7 +201,7 @@
     }
 
     public void dispose() {
-        //Unregister for all events
+        // Unregister for all events.
         cm.unregisterForAvailable(this);
         cm.unregisterForRadioStateChanged(this);
         cm.unregisterForNetworkStateChanged(this);
@@ -230,7 +224,7 @@
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    /*protected*/ void registerForGprsAttached(Handler h, int what, Object obj) {
+    void registerForGprsAttached(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         gprsAttachedRegistrants.add(r);
 
@@ -239,11 +233,11 @@
         }
     }
 
-    /*protected*/ void unregisterForGprsAttached(Handler h) {
+    void unregisterForGprsAttached(Handler h) {
         gprsAttachedRegistrants.remove(h);
     }
 
-    /*protected*/  void registerForNetworkAttach(Handler h, int what, Object obj) {
+    void registerForNetworkAttach(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         networkAttachedRegistrants.add(r);
 
@@ -252,16 +246,17 @@
         }
     }
 
-    /*protected*/  void unregisterForNetworkAttach(Handler h) {
+    void unregisterForNetworkAttach(Handler h) {
         networkAttachedRegistrants.remove(h);
     }
+
     /**
      * Registration point for transition into GPRS detached.
      * @param h handler to notify
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    /*protected*/ void registerForGprsDetached(Handler h, int what, Object obj) {
+    void registerForGprsDetached(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         gprsDetachedRegistrants.add(r);
 
@@ -270,7 +265,7 @@
         }
     }
 
-    /*protected*/  void unregisterForGprsDetached(Handler h) {
+    void unregisterForGprsDetached(Handler h) {
         gprsDetachedRegistrants.remove(h);
     }
 
@@ -280,7 +275,7 @@
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    /*protected*/  void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
+    void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
         Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
         Registrant r = new Registrant(h, what, obj);
         psRestrictEnabledRegistrants.add(r);
@@ -290,7 +285,7 @@
         }
     }
 
-    /*protected*/  void unregisterForPsRestrictedEnabled(Handler h) {
+    void unregisterForPsRestrictedEnabled(Handler h) {
         psRestrictEnabledRegistrants.remove(h);
     }
 
@@ -300,7 +295,7 @@
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    /*protected*/  void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
+    void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
         Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
         Registrant r = new Registrant(h, what, obj);
         psRestrictDisabledRegistrants.add(r);
@@ -310,25 +305,20 @@
         }
     }
 
-    /*protected*/  void unregisterForPsRestrictedDisabled(Handler h) {
+    void unregisterForPsRestrictedDisabled(Handler h) {
         psRestrictDisabledRegistrants.remove(h);
     }
 
-    /*protected*/ boolean getDataRoaming() {
+    boolean getDataRoaming() {
         return mDataRoaming;
     }
 
-    //***** Called from GSMPhone
-    public void
-    getLacAndCid(Message onComplete) {
+    public void getLacAndCid(Message onComplete) {
         cm.getRegistrationState(obtainMessage(
                         EVENT_GET_LOC_DONE, onComplete));
     }
 
-
-    //***** Overridden from ServiceStateTracker
-    public void
-    handleMessage (Message msg) {
+    public void handleMessage (Message msg) {
         AsyncResult ar;
         int[] ints;
         String[] strings;
@@ -529,10 +519,7 @@
         }
     }
 
-    //***** Private Instance Methods
-
-    protected void setPowerStateToDesired()
-    {
+    protected void setPowerStateToDesired() {
         // If we want it on and it's off, turn it on
         if (mDesiredPowerState
             && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
@@ -593,9 +580,7 @@
     /**
      * Handle the result of one of the pollState()-related requests
      */
-
-    protected void
-    handlePollStateResult (int what, AsyncResult ar) {
+    protected void handlePollStateResult (int what, AsyncResult ar) {
         int ints[];
         String states[];
 
@@ -726,9 +711,7 @@
      * and start over again if the radio notifies us that some
      * event has changed
      */
-
-    private void
-    pollState() {
+    private void pollState() {
         pollingContext = new int[1];
         pollingContext[0] = 0;
 
@@ -828,8 +811,7 @@
         return ret;
     }
 
-    private void
-    pollStateDone() {
+    private void pollStateDone() {
         if (DBG) {
             Log.d(LOG_TAG, "Poll ServiceState done: " +
                 " oldSS=[" + ss + "] newSS=[" + newSS +
@@ -882,7 +864,7 @@
         newSS.setStateOutOfService(); // clean slate for next time
 
         if (hasNetworkTypeChanged) {
-            phone.setSystemProperty(PROPERTY_DATA_NETWORK_TYPE,
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
                     networkTypeToString(networkType));
         }
 
@@ -895,14 +877,14 @@
         if (hasChanged) {
             String operatorNumeric;
 
-            phone.setSystemProperty(PROPERTY_OPERATOR_ALPHA,
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
                 ss.getOperatorAlphaLong());
 
             operatorNumeric = ss.getOperatorNumeric();
-            phone.setSystemProperty(PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
 
             if (operatorNumeric == null) {
-                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, "");
+                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
             } else {
                 String iso = "";
                 try{
@@ -914,7 +896,7 @@
                     Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
                 }
 
-                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, iso);
+                phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, iso);
                 mGotCountryCode = true;
 
                 if (mNeedFixZone) {
@@ -957,7 +939,7 @@
                 }
             }
 
-            phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
+            phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
                 ss.getRoaming() ? "true" : "false");
 
             updateSpnDisplay();
@@ -1052,8 +1034,7 @@
         return guess;
     }
 
-    private void
-    queueNextSignalStrengthPoll() {
+    private void queueNextSignalStrengthPoll() {
         if (dontPollSignalStrength || (cm.getRadioState().isCdma())) {
             // The radio is telling us about signal strength changes
             // we don't have to ask it
@@ -1075,8 +1056,7 @@
      *  send signal-strength-changed notification if changed
      *  Called both for solicited and unsolicited signal stength updates
      */
-    private void
-    onSignalStrengthResult(AsyncResult ar) {
+    private void onSignalStrengthResult(AsyncResult ar) {
         SignalStrength oldSignalStrength = mSignalStrength;
         int rssi = 99;
 
@@ -1117,8 +1097,7 @@
      *
      * @param ar an int value of RIL_RESTRICTED_STATE_*
      */
-    private void onRestrictedStateChanged(AsyncResult ar)
-    {
+    private void onRestrictedStateChanged(AsyncResult ar) {
         Log.d(LOG_TAG, "[DSAC DEB] " + "onRestrictedStateChanged");
         RestrictedState newRs = new RestrictedState();
 
@@ -1207,8 +1186,7 @@
     }
 
     /** code is registration state 0-5 from TS 27.007 7.2 */
-    private int
-    regCodeToServiceState(int code) {
+    private int regCodeToServiceState(int code) {
         switch (code) {
             case 0:
             case 2: // 2 is "searching"
@@ -1234,8 +1212,7 @@
      * code is registration state 0-5 from TS 27.007 7.2
      * returns true if registered roam, false otherwise
      */
-    private boolean
-    regCodeIsRoaming (int code) {
+    private boolean regCodeIsRoaming (int code) {
         // 5 is  "in service -- roam"
         return 5 == code;
     }
@@ -1247,9 +1224,8 @@
      * @param s ServiceState hold current ons
      * @return true for roaming state set
      */
-    private
-    boolean isRoamingBetweenOperators(boolean gsmRoaming, ServiceState s) {
-        String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
+    private boolean isRoamingBetweenOperators(boolean gsmRoaming, ServiceState s) {
+        String spn = SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "empty");
 
         String onsl = s.getOperatorAlphaLong();
         String onss = s.getOperatorAlphaShort();
@@ -1257,7 +1233,8 @@
         boolean equalsOnsl = onsl != null && spn.equals(onsl);
         boolean equalsOnss = onss != null && spn.equals(onss);
 
-        String simNumeric = SystemProperties.get(PROPERTY_ICC_OPERATOR_NUMERIC, "");
+        String simNumeric = SystemProperties.get(
+                TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
         String  operatorNumeric = s.getOperatorNumeric();
 
         boolean equalsMcc = true;
@@ -1270,8 +1247,7 @@
         return gsmRoaming && !(equalsMcc && (equalsOnsl || equalsOnss));
     }
 
-    private static
-    int twoDigitsAt(String s, int offset) {
+    private static int twoDigitsAt(String s, int offset) {
         int a, b;
 
         a = Character.digit(s.charAt(offset), 10);
@@ -1289,7 +1265,7 @@
      * @return The current GPRS state. IN_SERVICE is the same as "attached"
      * and OUT_OF_SERVICE is the same as detached.
      */
-    /*package*/ int getCurrentGprsState() {
+    int getCurrentGprsState() {
         return gprsState;
     }
 
@@ -1337,10 +1313,7 @@
     /**
      * nitzReceiveTime is time_t that the NITZ time was posted
      */
-
-    private
-    void setTimeFromNITZString (String nitz, long nitzReceiveTime)
-    {
+    private void setTimeFromNITZString (String nitz, long nitzReceiveTime) {
         // "yy/mm/dd,hh:mm:ss(+/-)tz"
         // tz is in number of quarter-hours
 
@@ -1404,7 +1377,7 @@
                 zone = TimeZone.getTimeZone( tzname );
             }
 
-            String iso = SystemProperties.get(PROPERTY_OPERATOR_ISO_COUNTRY);
+            String iso = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY);
 
             if (zone == null) {
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 93721ff..569cf25 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -337,7 +337,7 @@
      *         Returns null on encode error.
      */
     public static SubmitPdu getSubmitPdu(String scAddress,
-            String destinationAddress, short destinationPort, byte[] data,
+            String destinationAddress, int destinationPort, byte[] data,
             boolean statusReportRequested) {
 
         SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
index 02af547..98d4c25 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -32,12 +32,10 @@
 
 import android.util.Log;
 
-import java.util.Iterator;
-
-import java.lang.Integer;
+import java.util.ArrayList;
 
 public class CdmaSmsTest extends AndroidTestCase {
-    private final static String LOG_TAG = "CDMA";
+    private final static String LOG_TAG = "XXX CdmaSmsTest XXX";
 
     @SmallTest
     public void testCdmaSmsAddrParsing() throws Exception {
@@ -530,29 +528,19 @@
 
     @SmallTest
     public void testNumberOfMessages() throws Exception {
+        // Note that the message text below does not properly reflect
+        // the message count.  The author of these messages was
+        // apparently unaware that the values are bcd encoded, and the
+        // values being tested against (not the ones in the message
+        // text) are actually correct.
         String pdu1 = "000310409001124896a794e07595f69f199540ea759a0dc8e00b0163";
         BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
         assertEquals("Test Voice mail 99", bd1.userData.payloadStr);
-        assertEquals(99, bd1.numberOfMessages);
+        assertEquals(63, bd1.numberOfMessages);
         String pdu2 = "00031040900113489ea794e07595f69f199540ea759a0988c0600b0164";
         BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
         assertEquals("Test Voice mail 100", bd2.userData.payloadStr);
-        assertEquals(100, bd2.numberOfMessages);
-    }
-
-    @SmallTest
-    public void testNumberOfMessagesFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "test message count";
-        bearerData.userData = userData;
-        bearerData.numberOfMessages = 27;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(bearerData.numberOfMessages, revBearerData.numberOfMessages);
+        assertEquals(64, bd2.numberOfMessages);
     }
 
     @SmallTest
@@ -766,7 +754,6 @@
     public void testDisplayMode() throws Exception {
         String pdu1 = "0003104090010c485f4194dfea34becf61b8400f0100";
         BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        //Log.d(LOG_TAG, "bd1 = " + bd1);
         assertEquals(bd1.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
         String pdu2 = "0003104090010c485f4194dfea34becf61b8400f0140";
         BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
@@ -830,4 +817,30 @@
         BearerData revBearerData = BearerData.decode(encodedSms);
         assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
     }
+
+    @SmallTest
+    public void testFragmentText() throws Exception {
+        // Valid 160 character ASCII text.
+        String text1 = "123456789012345678901234567890123456789012345678901234567890" +
+                "1234567890123456789012345678901234567890123456789012345678901234567890" +
+                "12345678901234567890123456789[";
+        TextEncodingDetails ted = SmsMessage.calculateLength(text1, false);
+        assertEquals(ted.msgCount, 1);
+        assertEquals(ted.codeUnitCount, 160);
+        assertEquals(ted.codeUnitSize, 1);
+        ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text1);
+        assertEquals(fragments.size(), 1);
+        // Valid 160 character GSM text -- the last character is
+        // non-ASCII, and so this will currently generate a singleton
+        // EMS message, which is not necessarily supported by Verizon.
+        String text2 = "123456789012345678901234567890123456789012345678901234567890" +
+                "1234567890123456789012345678901234567890123456789012345678901234567890" +
+                "12345678901234567890123456789\u00a3";  // Trailing pound-currency sign.
+        ted = SmsMessage.calculateLength(text2, false);
+        assertEquals(ted.msgCount, 1);
+        assertEquals(ted.codeUnitCount, 160);
+        assertEquals(ted.codeUnitSize, 1);
+        fragments = android.telephony.SmsMessage.fragmentText(text2);
+        assertEquals(fragments.size(), 1);
+    }
 }
diff --git a/tests/DumpRenderTree/assets/run_layout_tests.py b/tests/DumpRenderTree/assets/run_layout_tests.py
index c056de5..c3e6b5b 100755
--- a/tests/DumpRenderTree/assets/run_layout_tests.py
+++ b/tests/DumpRenderTree/assets/run_layout_tests.py
@@ -175,7 +175,7 @@
   # Count crashed tests.
   crashed_tests = []
 
-  timeout_ms = '5000'
+  timeout_ms = '30000'
   if options.time_out_ms:
     timeout_ms = options.time_out_ms
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index 2eecef8..b980710 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -16,6 +16,7 @@
 
 package com.android.dumprendertree;
 
+import com.android.dumprendertree.TestShellActivity.DumpDataType;
 import com.android.dumprendertree.forwarder.AdbUtils;
 import com.android.dumprendertree.forwarder.ForwardServer;
 
@@ -313,6 +314,7 @@
             }
 
             public void timedOut(String url) {
+                Log.v(LOGTAG, "layout timeout: " + url);
             }
         });
 
@@ -398,7 +400,8 @@
         if (resume)
             resumeTestList();
 
-        TestShellActivity activity = (TestShellActivity) getActivity();
+        TestShellActivity activity = getActivity();
+        activity.setDefaultDumpDataType(DumpDataType.DUMP_AS_TEXT);
 
         // Run tests.
         int addr = -1;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 4c9853d..10849921 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -428,10 +428,15 @@
     }
 }
 
-static bool applyFileOverlay(const sp<AaptAssets>& assets,
+static bool applyFileOverlay(Bundle *bundle,
+                             const sp<AaptAssets>& assets,
                              const sp<ResourceTypeSet>& baseSet,
                              const char *resType)
 {
+    if (bundle->getVerbose()) {
+        printf("applyFileOverlay for %s\n", resType);
+    }
+
     // Replace any base level files in this category with any found from the overlay
     // Also add any found only in the overlay.
     sp<AaptAssets> overlay = assets->getOverlay();
@@ -450,6 +455,9 @@
             // non-overlay "baseset".
             size_t overlayCount = overlaySet->size();
             for (size_t overlayIndex=0; overlayIndex<overlayCount; overlayIndex++) {
+                if (bundle->getVerbose()) {
+                    printf("trying overlaySet Key=%s\n",overlaySet->keyAt(overlayIndex).string());
+                }
                 size_t baseIndex = baseSet->indexOfKey(overlaySet->keyAt(overlayIndex));
                 if (baseIndex < UNKNOWN_ERROR) {
                     // look for same flavor.  For a given file (strings.xml, for example)
@@ -457,18 +465,36 @@
                     // the same flavor.
                     sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex);
                     sp<AaptGroup> baseGroup = baseSet->valueAt(baseIndex);
-                   
-                    DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles = 
-                            baseGroup->getFiles();
-                    DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles = 
+
+                    DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles =
                             overlayGroup->getFiles();
+                    if (bundle->getVerbose()) {
+                        DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
+                                baseGroup->getFiles();
+                        for (size_t i=0; i < baseFiles.size(); i++) {
+                            printf("baseFile %d has flavor %s\n", i,
+                                    baseFiles.keyAt(i).toString().string());
+                        }
+                        for (size_t i=0; i < overlayFiles.size(); i++) {
+                            printf("overlayFile %d has flavor %s\n", i,
+                                    overlayFiles.keyAt(i).toString().string());
+                        }
+                    }
+
                     size_t overlayGroupSize = overlayFiles.size();
-                    for (size_t overlayGroupIndex = 0; 
-                            overlayGroupIndex<overlayGroupSize; 
+                    for (size_t overlayGroupIndex = 0;
+                            overlayGroupIndex<overlayGroupSize;
                             overlayGroupIndex++) {
-                        size_t baseFileIndex = 
-                                baseFiles.indexOfKey(overlayFiles.keyAt(overlayGroupIndex));
+                        size_t baseFileIndex =
+                                baseGroup->getFiles().indexOfKey(overlayFiles.
+                                keyAt(overlayGroupIndex));
                         if(baseFileIndex < UNKNOWN_ERROR) {
+                            if (bundle->getVerbose()) {
+                                printf("found a match (%d) for overlay file %s, for flavor %s\n",
+                                        baseFileIndex,
+                                        overlayGroup->getLeaf().string(),
+                                        overlayFiles.keyAt(overlayGroupIndex).toString().string());
+                            }
                             baseGroup->removeFile(baseFileIndex);
                         } else {
                             // didn't find a match fall through and add it..
@@ -482,11 +508,11 @@
                             overlaySet->valueAt(overlayIndex));
                     // make sure all flavors are defined in the resources.
                     sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex);
-                    DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles = 
+                    DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles =
                             overlayGroup->getFiles();
                     size_t overlayGroupSize = overlayFiles.size();
-                    for (size_t overlayGroupIndex = 0; 
-                            overlayGroupIndex<overlayGroupSize; 
+                    for (size_t overlayGroupIndex = 0;
+                            overlayGroupIndex<overlayGroupSize;
                             overlayGroupIndex++) {
                         assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
                     }
@@ -623,13 +649,13 @@
         current = current->getOverlay();
     }
     // apply the overlay files to the base set
-    if (!applyFileOverlay(assets, drawables, "drawable") ||
-            !applyFileOverlay(assets, layouts, "layout") ||
-            !applyFileOverlay(assets, anims, "anim") ||
-            !applyFileOverlay(assets, xmls, "xml") ||
-            !applyFileOverlay(assets, raws, "raw") ||
-            !applyFileOverlay(assets, colors, "color") ||
-            !applyFileOverlay(assets, menus, "menu")) {
+    if (!applyFileOverlay(bundle, assets, drawables, "drawable") ||
+            !applyFileOverlay(bundle, assets, layouts, "layout") ||
+            !applyFileOverlay(bundle, assets, anims, "anim") ||
+            !applyFileOverlay(bundle, assets, xmls, "xml") ||
+            !applyFileOverlay(bundle, assets, raws, "raw") ||
+            !applyFileOverlay(bundle, assets, colors, "color") ||
+            !applyFileOverlay(bundle, assets, menus, "menu")) {
         return UNKNOWN_ERROR;
     }