Merge change 6232

* changes:
  frameworks/base: Update mPdu in createFromPdu
diff --git a/api/current.xml b/api/current.xml
index c93f706..2eecdbe 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -112903,6 +112903,344 @@
 </field>
 </class>
 </package>
+<package name="android.speech.tts"
+>
+<class name="TextToSpeech"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="TextToSpeech"
+ type="android.speech.tts.TextToSpeech"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="listener" type="android.speech.tts.TextToSpeech.OnInitListener">
+</parameter>
+</constructor>
+<method name="addSpeech"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.String">
+</parameter>
+<parameter name="packagename" type="java.lang.String">
+</parameter>
+<parameter name="resourceId" type="int">
+</parameter>
+</method>
+<method name="addSpeech"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.String">
+</parameter>
+<parameter name="filename" type="java.lang.String">
+</parameter>
+</method>
+<method name="getLanguage"
+ return="java.util.Locale"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isLanguageAvailable"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loc" type="java.util.Locale">
+</parameter>
+</method>
+<method name="isSpeaking"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="playEarcon"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="earcon" type="java.lang.String">
+</parameter>
+<parameter name="queueMode" type="int">
+</parameter>
+<parameter name="params" type="java.util.HashMap&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="playSilence"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="durationInMs" type="long">
+</parameter>
+<parameter name="queueMode" type="int">
+</parameter>
+</method>
+<method name="setLanguage"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loc" type="java.util.Locale">
+</parameter>
+</method>
+<method name="setPitch"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pitch" type="float">
+</parameter>
+</method>
+<method name="setSpeechRate"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="speechRate" type="float">
+</parameter>
+</method>
+<method name="shutdown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="speak"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.String">
+</parameter>
+<parameter name="queueMode" type="int">
+</parameter>
+<parameter name="params" type="java.util.HashMap&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+</method>
+<method name="stop"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="synthesizeToFile"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.String">
+</parameter>
+<parameter name="params" type="java.util.HashMap&lt;java.lang.String, java.lang.String&gt;">
+</parameter>
+<parameter name="filename" type="java.lang.String">
+</parameter>
+</method>
+<field name="TTS_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_LANG_AVAILABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_LANG_COUNTRY_AVAILABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_LANG_COUNTRY_VAR_AVAILABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_LANG_MISSING_DATA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_LANG_NOT_SUPPORTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_QUEUE_ADD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_QUEUE_FLUSH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_SUCCESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="TextToSpeech.OnInitListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onInit"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="status" type="int">
+</parameter>
+</method>
+</interface>
+</package>
 <package name="android.telephony"
 >
 <class name="CellLocation"
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index c90b862..ee3ec1a 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -97,6 +97,11 @@
             return;
         }
 
+        if ("wipe".equals(op)) {
+            doWipe();
+            return;
+        }
+
         System.err.println("Unknown command");
         showUsage();
     }
@@ -183,6 +188,22 @@
         }
     }
 
+    private void doWipe() {
+        String pkg = nextArg();
+        if (pkg == null) {
+            showUsage();
+            return;
+        }
+
+        try {
+            mBmgr.clearBackupData(pkg);
+            System.out.println("Wiped backup data for " + pkg);
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(BMGR_NOT_RUNNING_ERR);
+        }
+    }
+
     private void doList() {
         String arg = nextArg();     // sets, transports, packages set#
         if ("transports".equals(arg)) {
@@ -343,6 +364,7 @@
         System.err.println("       bmgr transport WHICH");
         System.err.println("       bmgr restore TOKEN");
         System.err.println("       bmgr run");
+        System.err.println("       bmgr wipe PACKAGE");
         System.err.println("");
         System.err.println("The 'backup' command schedules a backup pass for the named package.");
         System.err.println("Note that the backup pass will effectively be a no-op if the package");
@@ -373,5 +395,9 @@
         System.err.println("The 'run' command causes any scheduled backup operation to be initiated");
         System.err.println("immediately, without the usual waiting period for batching together");
         System.err.println("data changes.");
+        System.err.println("");
+        System.err.println("The 'wipe' command causes all backed-up data for the given package to be");
+        System.err.println("erased from the current transport's storage.  The next backup operation");
+        System.err.println("that the given application performs will rewrite its entire data set.");
     }
 }
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index 1f11762..d4933ac 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -32,10 +32,24 @@
     /**
      * Tell the system service that the caller has made changes to its
      * data, and therefore needs to undergo an incremental backup pass.
+     *
+     * Any application can invoke this method for its own package, but
+     * only callers who hold the android.permission.BACKUP permission
+     * may invoke it for arbitrary packages.
      */
     void dataChanged(String packageName);
 
     /**
+     * Erase all backed-up data for the given package from the storage
+     * destination.
+     *
+     * Any application can invoke this method for its own package, but
+     * only callers who hold the android.permission.BACKUP permission
+     * may invoke it for arbitrary packages.
+     */
+    void clearBackupData(String packageName);
+
+    /**
      * Notifies the Backup Manager Service that an agent has become available.  This
      * method is only invoked by the Activity Manager.
      */
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 3ce951f..091bc17 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -371,7 +371,7 @@
     }
     private native final void native_takePicture();
 
-    // These match the enum in libs/android_runtime/android_hardware_Camera.cpp
+    // These match the enum in include/ui/Camera.h
     /** Unspecified camerar error.  @see #ErrorCallback */
     public static final int CAMERA_ERROR_UNKNOWN = 1;
     /** Media server died. In this case, the application must release the
diff --git a/core/java/android/net/http/ConnectionThread.java b/core/java/android/net/http/ConnectionThread.java
index 8e759e2..1d0db2b 100644
--- a/core/java/android/net/http/ConnectionThread.java
+++ b/core/java/android/net/http/ConnectionThread.java
@@ -32,8 +32,8 @@
     static final int WAIT_TICK = 1000;
 
     // Performance probe
-    long mStartThreadTime;
     long mCurrentThreadTime;
+    long mTotalThreadTime;
 
     private boolean mWaiting;
     private volatile boolean mRunning = true;
@@ -71,10 +71,18 @@
         android.os.Process.setThreadPriority(
                 android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
 
-        mStartThreadTime = -1;
-        mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
+        // these are used to get performance data. When it is not in the timing,
+        // mCurrentThreadTime is 0. When it starts timing, mCurrentThreadTime is
+        // first set to -1, it will be set to the current thread time when the
+        // next request starts.
+        mCurrentThreadTime = 0;
+        mTotalThreadTime = 0;
 
         while (mRunning) {
+            if (mCurrentThreadTime == -1) {
+                mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
+            }
+
             Request request;
 
             /* Get a request to process */
@@ -86,14 +94,14 @@
                     if (HttpLog.LOGV) HttpLog.v("ConnectionThread: Waiting for work");
                     mWaiting = true;
                     try {
-                        if (mStartThreadTime != -1) {
-                            mCurrentThreadTime = SystemClock
-                                    .currentThreadTimeMillis();
-                        }
                         mRequestFeeder.wait();
                     } catch (InterruptedException e) {
                     }
                     mWaiting = false;
+                    if (mCurrentThreadTime != 0) {
+                        mCurrentThreadTime = SystemClock
+                                .currentThreadTimeMillis();
+                    }
                 }
             } else {
                 if (HttpLog.LOGV) HttpLog.v("ConnectionThread: new request " +
@@ -123,6 +131,12 @@
                     mConnection.closeConnection();
                 }
                 mConnection = null;
+
+                if (mCurrentThreadTime > 0) {
+                    long start = mCurrentThreadTime;
+                    mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
+                    mTotalThreadTime += mCurrentThreadTime - start;
+                }
             }
 
         }
diff --git a/core/java/android/net/http/RequestQueue.java b/core/java/android/net/http/RequestQueue.java
index 54a1cce..4d3e7c3 100644
--- a/core/java/android/net/http/RequestQueue.java
+++ b/core/java/android/net/http/RequestQueue.java
@@ -279,7 +279,9 @@
 
         public void startTiming() {
             for (int i = 0; i < mConnectionCount; i++) {
-                mThreads[i].mStartThreadTime = mThreads[i].mCurrentThreadTime;
+                ConnectionThread rt = mThreads[i];
+                rt.mCurrentThreadTime = -1;
+                rt.mTotalThreadTime = 0;
             }
             mTotalRequest = 0;
             mTotalConnection = 0;
@@ -289,12 +291,14 @@
             int totalTime = 0;
             for (int i = 0; i < mConnectionCount; i++) {
                 ConnectionThread rt = mThreads[i];
-                totalTime += (rt.mCurrentThreadTime - rt.mStartThreadTime);
-                rt.mStartThreadTime = -1;
+                if (rt.mCurrentThreadTime != -1) {
+                    totalTime += rt.mTotalThreadTime;
+                }
+                rt.mCurrentThreadTime = 0;
             }
             Log.d("Http", "Http thread used " + totalTime + " ms " + " for "
                     + mTotalRequest + " requests and " + mTotalConnection
-                    + " connections");
+                    + " new connections");
         }
 
         void logState() {
diff --git a/core/java/android/speech/tts/ITts.aidl b/core/java/android/speech/tts/ITts.aidl
index 15f3876..5612ecd 100755
--- a/core/java/android/speech/tts/ITts.aidl
+++ b/core/java/android/speech/tts/ITts.aidl
@@ -33,8 +33,6 @@
 

     void speak(in String text, in int queueMode, in String[] params);

 

-    void speakIpa(in String ipaText, in int queueMode, in String[] params);

-

     boolean isSpeaking();

 

     void stop();

@@ -49,9 +47,7 @@
 

     void setLanguage(in String language, in String country, in String variant);

 

-    boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory);
-

-    boolean synthesizeIpaToFile(in String ipaText, in String[] params, in String outputDirectory);

+    boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory);

 

     void playEarcon(in String earcon, in int queueMode, in String[] params);

 

diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index b245713..f714dd9 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -31,11 +31,10 @@
 
 /**
  *
- * Synthesizes speech from text.
+ * Synthesizes speech from text for immediate playback or to create a sound file.
  *
- * {@hide}
  */
-//TODO #TTS# review + complete javadoc + add links to constants
+//TODO complete javadoc + add links to constants
 public class TextToSpeech {
 
     /**
@@ -118,7 +117,12 @@
         public static final int CHECK_VOICE_DATA_BAD_DATA = -1;
         public static final int CHECK_VOICE_DATA_MISSING_DATA = -2;
         public static final int CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD = -3;
-        
+
+        // return codes for a TTS engine's check data activity
+        public static final String VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
+        public static final String VOICE_DATA_FILES = "dataFiles";
+        public static final String VOICE_DATA_FILES_INFO = "dataFilesInfo";
+
         // keys for the parameters passed with speak commands
         public static final String TTS_KEY_PARAM_RATE = "rate";
         public static final String TTS_KEY_PARAM_LANGUAGE = "language";
@@ -365,54 +369,6 @@
 
 
     /**
-     * Speaks the IPA string using the specified queuing strategy and speech
-     * parameters. Note that the speech parameters are not universally supported
-     * by all engines and will be treated as a hint. The TTS library will try to
-     * fulfill these parameters as much as possible, but there is no guarantee
-     * that the voice used will have the properties specified.
-     *
-     * @param ipaText
-     *            The string of IPA text to be spoken.
-     * @param queueMode
-     *            The queuing strategy to use.
-     *            See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
-     * @param params
-     *            The hashmap of speech parameters to be used.
-     *
-     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
-     *
-     * {@hide}
-     */
-    public int speakIpa(String ipaText, int queueMode, HashMap<String,String> params)
-    {
-        synchronized (mStartLock) {
-            Log.i("TTS received: ", ipaText);
-            if (!mStarted) {
-                return TTS_ERROR;
-            }
-            try {
-                // TODO support extra parameters, passing cache of current parameters for the moment
-                mITts.speakIpa(ipaText, queueMode, mCachedParams);
-                return TTS_SUCCESS;
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                mStarted = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                mStarted = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                mStarted = false;
-                initTts();
-            }
-            return TTS_ERROR;
-        }
-    }
-
-
-    /**
      * Plays the earcon using the specified queueing mode and parameters.
      *
      * @param earcon
@@ -750,48 +706,4 @@
         }
     }
 
-
-    /**
-     * Synthesizes the given IPA text to a file using the specified parameters.
-     *
-     * @param text
-     *            The String of text that should be synthesized
-     * @param params
-     *            A hashmap of parameters.
-     * @param filename
-     *            The string that gives the full output filename; it should be
-     *            something like "/sdcard/myappsounds/mysound.wav".
-     *
-     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
-     *
-     * {@hide}
-     */
-    public int synthesizeIpaToFile(String ipaText,
-            HashMap<String,String> params, String filename) {
-        synchronized (mStartLock) {
-            if (!mStarted) {
-                return TTS_ERROR;
-            }
-            try {
-                // TODO support extra parameters, passing null for the moment
-                if (mITts.synthesizeIpaToFile(ipaText, null, filename)){
-                    return TTS_SUCCESS;
-                }
-            } catch (RemoteException e) {
-                // TTS died; restart it.
-                mStarted = false;
-                initTts();
-            } catch (NullPointerException e) {
-                // TTS died; restart it.
-                mStarted = false;
-                initTts();
-            } catch (IllegalStateException e) {
-                // TTS died; restart it.
-                mStarted = false;
-                initTts();
-            }
-            return TTS_ERROR;
-        }
-    }
-
 }
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 9a8c3c0..3b67fb6 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -641,7 +641,40 @@
     //--------------------------------------------------------------------------
 
     // Performance probe
+    private static final boolean PERF_PROBE = false;
     private long mWebCoreThreadTime;
+    private long mWebCoreIdleTime;
+
+    /*
+     * If PERF_PROBE is true, this block needs to be added to MessageQueue.java.
+     * startWait() and finishWait() should be called before and after wait().
+
+    private WaitCallback mWaitCallback = null;
+    public static interface WaitCallback {
+        void startWait();
+        void finishWait();
+    }
+    public final void setWaitCallback(WaitCallback callback) {
+        mWaitCallback = callback;
+    }
+    */
+
+    // un-comment this block if PERF_PROBE is true
+    /*
+    private IdleCallback mIdleCallback = new IdleCallback();
+
+    private final class IdleCallback implements MessageQueue.WaitCallback {
+        private long mStartTime = 0;
+
+        public void finishWait() {
+            mWebCoreIdleTime += SystemClock.uptimeMillis() - mStartTime;
+        }
+
+        public void startWait() {
+            mStartTime = SystemClock.uptimeMillis();
+        }
+    }
+    */
 
     public void onPageStarted(String url, Bitmap favicon) {
         // Do an unsynchronized quick check to avoid posting if no callback has
@@ -650,9 +683,12 @@
             return;
         }
         // Performance probe
-        if (false) {
+        if (PERF_PROBE) {
             mWebCoreThreadTime = SystemClock.currentThreadTimeMillis();
+            mWebCoreIdleTime = 0;
             Network.getInstance(mContext).startTiming();
+            // un-comment this if PERF_PROBE is true
+//            Looper.myQueue().setWaitCallback(mIdleCallback);
         }
         Message msg = obtainMessage(PAGE_STARTED);
         msg.obj = favicon;
@@ -667,10 +703,12 @@
             return;
         }
         // Performance probe
-        if (false) {
+        if (PERF_PROBE) {
+            // un-comment this if PERF_PROBE is true
+//            Looper.myQueue().setWaitCallback(null);
             Log.d("WebCore", "WebCore thread used " + 
                     (SystemClock.currentThreadTimeMillis() - mWebCoreThreadTime)
-                    + " ms");
+                    + " ms and idled " + mWebCoreIdleTime + " ms");
             Network.getInstance(mContext).stopTiming();
         }
         Message msg = obtainMessage(PAGE_FINISHED, url);
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 973cb010..5b2c0e2 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -24,6 +24,7 @@
 import android.os.Message;
 import android.util.Log;
 import android.view.View;
+import android.webkit.ViewManager.ChildView;
 import android.widget.MediaController;
 import android.widget.VideoView;
 
@@ -46,8 +47,6 @@
 
     // The singleton instance.
     private static HTML5VideoViewProxy sInstance;
-    // The VideoView driven via this proxy.
-    private VideoView mVideoView;
     // The context object used to initialize the VideoView and the
     // MediaController.
     private Context mContext;
@@ -61,12 +60,6 @@
         super(Looper.getMainLooper());
         // Save the context object.
         mContext = context;
-        // Send a message to the UI thread to create the VideoView.
-        // This need to be done on the UI thread, or else the
-        // event Handlers used by the VideoView and MediaController
-        // will be attached to the wrong thread.
-        Message message = obtainMessage(INIT);
-        sendMessage(message);
     }
 
     @Override
@@ -74,25 +67,22 @@
         // This executes on the UI thread.
         switch (msg.what) {
             case INIT:
+                ChildView child = (ChildView) msg.obj;
                 // Create the video view and set a default controller.
-                mVideoView = new VideoView(mContext);
-                mVideoView.setMediaController(new MediaController(mContext));
+                VideoView v = new VideoView(mContext);
+                // This is needed because otherwise there will be a black square
+                // stuck on the screen.
+                v.setWillNotDraw(false);
+                v.setMediaController(new MediaController(mContext));
+                child.mView = v;
                 break;
             case PLAY:
-                // Check if the fullscreen video view is currently playing.
-                // If it is, ignore the message.
-                if (!mVideoView.isPlaying()) {
-                    HashMap<String, Object> map =
+                HashMap<String, Object> map =
                         (HashMap<String, Object>) msg.obj;
-                    String url = (String) map.get("url");
-                    WebView webview = (WebView) map.get("webview");
-                    WebChromeClient client = webview.getWebChromeClient();
-                    if (client != null) {
-                        mVideoView.setVideoURI(Uri.parse(url));
-                        mVideoView.start();
-                        client.onShowCustomView(mVideoView);
-                    }
-                }
+                String url = (String) map.get("url");
+                VideoView view = (VideoView) map.get("view");
+                view.setVideoURI(Uri.parse(url));
+                view.start();
                 break;
         }
     }
@@ -102,16 +92,35 @@
      * @param url is the URL of the video stream.
      * @param webview is the WebViewCore that is requesting the playback.
      */
-    public void play(String url, WebViewCore webviewCore) {
+    public void play(String url, ChildView child) {
         // We need to know the webview that is requesting the playback.
         Message message = obtainMessage(PLAY);
         HashMap<String, Object> map = new HashMap();
         map.put("url", url);
-        map.put("webview", webviewCore.getWebView());
+        map.put("view", child.mView);
         message.obj = map;
         sendMessage(message);
     }
 
+    public ChildView createView(WebViewCore core) {
+        WebView w = core.getWebView();
+        if (w == null) {
+            return null;
+        }
+        ChildView child = w.mViewManager.createView();
+        sendMessage(obtainMessage(INIT, child));
+        return child;
+    }
+
+    public void attachView(ChildView child, int x, int y, int width,
+            int height) {
+        child.attachView(x, y, width, height);
+    }
+
+    public void removeView(ChildView child) {
+        child.removeView();
+    }
+
     /**
      * The factory for HTML5VideoViewProxy instances. Right now,
      * it only produces a singleton.
diff --git a/core/java/android/webkit/ViewManager.java b/core/java/android/webkit/ViewManager.java
new file mode 100644
index 0000000..476e85c
--- /dev/null
+++ b/core/java/android/webkit/ViewManager.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.AbsoluteLayout;
+
+import java.util.ArrayList;
+
+class ViewManager {
+    private final WebView mWebView;
+    private final ArrayList<ChildView> mChildren = new ArrayList<ChildView>();
+    private boolean mHidden;
+
+    class ChildView {
+        int x;
+        int y;
+        int width;
+        int height;
+        View mView; // generic view to show
+
+        ChildView() {
+        }
+
+        void setBounds(int x, int y, int width, int height) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+        }
+
+        void attachView(int x, int y, int width, int height) {
+            if (mView == null) {
+                return;
+            }
+            setBounds(x, y, width, height);
+            final AbsoluteLayout.LayoutParams lp =
+                    new AbsoluteLayout.LayoutParams(ctv(width), ctv(height),
+                            ctv(x), ctv(y));
+            mWebView.mPrivateHandler.post(new Runnable() {
+                public void run() {
+                    // This method may be called multiple times. If the view is
+                    // already attached, just set the new LayoutParams,
+                    // otherwise attach the view and add it to the list of
+                    // children.
+                    if (mView.getParent() != null) {
+                        mView.setLayoutParams(lp);
+                    } else {
+                        mWebView.addView(mView, lp);
+                        mChildren.add(ChildView.this);
+                    }
+                }
+            });
+        }
+
+        void removeView() {
+            if (mView == null) {
+                return;
+            }
+            mWebView.mPrivateHandler.post(new Runnable() {
+                public void run() {
+                    mWebView.removeView(mView);
+                    mChildren.remove(ChildView.this);
+                }
+            });
+        }
+    }
+
+    ViewManager(WebView w) {
+        mWebView = w;
+    }
+
+    ChildView createView() {
+        return new ChildView();
+    }
+
+    // contentToView shorthand.
+    private int ctv(int val) {
+        return mWebView.contentToView(val);
+    }
+
+    void scaleAll() {
+        for (ChildView v : mChildren) {
+            View view = v.mView;
+            AbsoluteLayout.LayoutParams lp =
+                    (AbsoluteLayout.LayoutParams) view.getLayoutParams();
+            lp.width = ctv(v.width);
+            lp.height = ctv(v.height);
+            lp.x = ctv(v.x);
+            lp.y = ctv(v.y);
+            view.setLayoutParams(lp);
+        }
+    }
+
+    void hideAll() {
+        if (mHidden) {
+            return;
+        }
+        for (ChildView v : mChildren) {
+            v.mView.setVisibility(View.GONE);
+        }
+        mHidden = true;
+    }
+
+    void showAll() {
+        if (!mHidden) {
+            return;
+        }
+        for (ChildView v : mChildren) {
+            v.mView.setVisibility(View.VISIBLE);
+        }
+        mHidden = false;
+    }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 57b9ac3..61c0cb9 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -308,6 +308,9 @@
     // more key events.
     private int mTextGeneration;
 
+    // Used by WebViewCore to create child views.
+    /* package */ final ViewManager mViewManager;
+
     // The list of loaded plugins.
     private static PluginList sPluginList;
 
@@ -710,6 +713,8 @@
         mDatabase = WebViewDatabase.getInstance(context);
         mScroller = new Scroller(context);
 
+        mViewManager = new ViewManager(this);
+
         mZoomButtonsController = new ZoomButtonsController(this);
         mZoomButtonsController.setOnZoomListener(mZoomListener);
         // ZoomButtonsController positions the buttons at the bottom, but in
@@ -1688,7 +1693,7 @@
         return Math.round(x * mInvActualScale);
     }
 
-    private int contentToView(int x) {
+    /*package*/ int contentToView(int x) {
         return Math.round(x * mActualScale);
     }
 
@@ -1779,6 +1784,9 @@
                 mActualScale = scale;
                 mInvActualScale = 1 / scale;
 
+                // Scale all the child views
+                mViewManager.scaleAll();
+
                 // as we don't have animation for scaling, don't do animation
                 // for scrolling, as it causes weird intermediate state
                 //        pinScrollTo(Math.round(sx), Math.round(sy));
@@ -2716,6 +2724,8 @@
                         - (width >> 1), (int) (scrollFrame.centerY()
                         * mActualScale) - (height >> 1));
                 mTouchMode = TOUCH_DONE_MODE;
+                // Show all the child views once we are done.
+                mViewManager.showAll();
             } else {
                 mTouchMode = SCROLL_ZOOM_OUT;
             }
@@ -2879,6 +2889,8 @@
             mTouchMode = TOUCH_DONE_MODE;
             return;
         }
+        // Hide the child views while in this mode.
+        mViewManager.hideAll();
         startZoomScrollOut();
         mTouchMode = SCROLL_ZOOM_ANIMATION_OUT;
         invalidate();
@@ -3625,6 +3637,7 @@
     @Override
     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
         super.onScrollChanged(l, t, oldl, oldt);
+
         sendOurVisibleRect();
     }
 
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index 4bef265..af06965 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -83,13 +83,25 @@
     boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd);
 
     /**
-     * Finish sending application data to the backup destination.  This must be
-     * called after {@link #performBackup} to ensure that all data is sent.  Only
-     * when this method returns true can the backup be assumed to have succeeded.
+     * Erase the give application's data from the backup destination.  This clears
+     * out the given package's data from the current backup set, making it as though
+     * the app had never yet been backed up.  After this is called, {@link finishBackup}
+     * must be called to ensure that the operation is recorded successfully.
      *
      * @return false if errors occurred (the backup should be aborted and rescheduled),
      *   true if everything is OK so far (but {@link #finishBackup} must be called).
      */
+    boolean clearBackupData(in PackageInfo packageInfo);
+
+    /**
+     * Finish sending application data to the backup destination.  This must be
+     * called after {@link #performBackup} or {@link clearBackupData} to ensure that
+     * all data is sent.  Only when this method returns true can a backup be assumed
+     * to have succeeded.
+     *
+     * @return false if errors occurred (the backup should be aborted and rescheduled),
+     *   true if everything is OK.
+     */
     boolean finishBackup();
 
     /**
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index c5d9d403..2facce2 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -111,6 +111,17 @@
         }
     }
 
+    public boolean clearBackupData(PackageInfo packageInfo) {
+        if (DEBUG) Log.v(TAG, "clearBackupData() pkg=" + packageInfo.packageName);
+
+        File packageDir = new File(mDataDir, packageInfo.packageName);
+        for (File f : packageDir.listFiles()) {
+            f.delete();
+        }
+        packageDir.delete();
+        return true;
+    }
+
     public boolean finishBackup() throws RemoteException {
         if (DEBUG) Log.v(TAG, "finishBackup()");
         return true;
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 0420918..83d2502 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -38,12 +38,6 @@
     kErrorCallback = 5
 };
 
-enum CameraError {
-    kCameraErrorUnknown = 1,
-    kCameraErrorMediaServer = 100
-};
-
-
 struct fields_t {
     jfieldID    context;
     jfieldID    surface;
diff --git a/data/sounds/AudioPackage2.mk b/data/sounds/AudioPackage2.mk
index f24d05c..5dacc70 100644
--- a/data/sounds/AudioPackage2.mk
+++ b/data/sounds/AudioPackage2.mk
@@ -7,90 +7,90 @@
 # that have larger internal flash.
 # 
 
-local_path:= frameworks/base/data/sounds
+LOCAL_PATH:= frameworks/base/data/sounds
 
 PRODUCT_COPY_FILES += \
-	$(local_path)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
-	$(local_path)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
-	$(local_path)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
-	$(local_path)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
-	$(local_path)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
-	$(local_path)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \
-	$(local_path)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \
-	$(local_path)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
-	$(local_path)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \
-	$(local_path)/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \
-	$(local_path)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \
-	$(local_path)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \
-	$(local_path)/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \
-	$(local_path)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \
-	$(local_path)/newwavelabs/BentleyDubs.ogg:system/media/audio/ringtones/BentleyDubs.ogg \
-	$(local_path)/newwavelabs/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \
-	$(local_path)/newwavelabs/CaribbeanIce.ogg:system/media/audio/ringtones/CaribbeanIce.ogg \
-	$(local_path)/newwavelabs/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \
-	$(local_path)/newwavelabs/EtherShake.ogg:system/media/audio/ringtones/EtherShake.ogg \
-	$(local_path)/newwavelabs/FriendlyGhost.ogg:system/media/audio/ringtones/FriendlyGhost.ogg \
-	$(local_path)/newwavelabs/GameOverGuitar.ogg:system/media/audio/ringtones/GameOverGuitar.ogg \
-	$(local_path)/newwavelabs/Growl.ogg:system/media/audio/ringtones/Growl.ogg \
-	$(local_path)/newwavelabs/InsertCoin.ogg:system/media/audio/ringtones/InsertCoin.ogg \
-	$(local_path)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
-	$(local_path)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
-	$(local_path)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
-	$(local_path)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
-	$(local_path)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
-	$(local_path)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \
-	$(local_path)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
-	$(local_path)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
-	$(local_path)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
-	$(local_path)/newwavelabs/RomancingTheTone.ogg:system/media/audio/ringtones/RomancingTheTone.ogg \
-	$(local_path)/newwavelabs/SitarVsSitar.ogg:system/media/audio/ringtones/SitarVsSitar.ogg \
-	$(local_path)/newwavelabs/SpringyJalopy.ogg:system/media/audio/ringtones/SpringyJalopy.ogg \
-	$(local_path)/newwavelabs/Terminated.ogg:system/media/audio/ringtones/Terminated.ogg \
-	$(local_path)/newwavelabs/TwirlAway.ogg:system/media/audio/ringtones/TwirlAway.ogg \
-	$(local_path)/newwavelabs/VeryAlarmed.ogg:system/media/audio/ringtones/VeryAlarmed.ogg \
-	$(local_path)/newwavelabs/World.ogg:system/media/audio/ringtones/World.ogg \
-	$(local_path)/newwavelabs/CaffeineSnake.ogg:system/media/audio/notifications/CaffeineSnake.ogg \
-	$(local_path)/newwavelabs/DearDeer.ogg:system/media/audio/notifications/DearDeer.ogg \
-	$(local_path)/newwavelabs/DontPanic.ogg:system/media/audio/notifications/DontPanic.ogg \
-	$(local_path)/newwavelabs/Highwire.ogg:system/media/audio/notifications/Highwire.ogg \
-	$(local_path)/newwavelabs/KzurbSonar.ogg:system/media/audio/notifications/KzurbSonar.ogg \
-	$(local_path)/newwavelabs/OnTheHunt.ogg:system/media/audio/notifications/OnTheHunt.ogg \
-	$(local_path)/newwavelabs/Voila.ogg:system/media/audio/notifications/Voila.ogg \
-	$(local_path)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
-	$(local_path)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
-	$(local_path)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
-	$(local_path)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
-	$(local_path)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
-	$(local_path)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
-	$(local_path)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
-	$(local_path)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
-	$(local_path)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(local_path)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
-	$(local_path)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
-	$(local_path)/newwavelabs/CrazyDream.ogg:system/media/audio/ringtones/CrazyDream.ogg \
-	$(local_path)/newwavelabs/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg \
-	$(local_path)/newwavelabs/Big_Easy.ogg:system/media/audio/ringtones/Big_Easy.ogg \
-	$(local_path)/newwavelabs/Bollywood.ogg:system/media/audio/ringtones/Bollywood.ogg \
-	$(local_path)/newwavelabs/Cairo.ogg:system/media/audio/ringtones/Cairo.ogg \
-	$(local_path)/newwavelabs/Calypso_Steel.ogg:system/media/audio/ringtones/Calypso_Steel.ogg \
-	$(local_path)/newwavelabs/Champagne_Edition.ogg:system/media/audio/ringtones/Champagne_Edition.ogg \
-	$(local_path)/newwavelabs/Club_Cubano.ogg:system/media/audio/ringtones/Club_Cubano.ogg \
-	$(local_path)/newwavelabs/Eastern_Sky.ogg:system/media/audio/ringtones/Eastern_Sky.ogg \
-	$(local_path)/newwavelabs/Funk_Yall.ogg:system/media/audio/ringtones/Funk_Yall.ogg \
-	$(local_path)/newwavelabs/Savannah.ogg:system/media/audio/ringtones/Savannah.ogg \
-	$(local_path)/newwavelabs/Gimme_Mo_Town.ogg:system/media/audio/ringtones/Gimme_Mo_Town.ogg \
-	$(local_path)/newwavelabs/Glacial_Groove.ogg:system/media/audio/ringtones/Glacial_Groove.ogg \
-	$(local_path)/newwavelabs/Seville.ogg:system/media/audio/ringtones/Seville.ogg \
-	$(local_path)/newwavelabs/No_Limits.ogg:system/media/audio/ringtones/No_Limits.ogg \
-	$(local_path)/newwavelabs/Revelation.ogg:system/media/audio/ringtones/Revelation.ogg \
-	$(local_path)/newwavelabs/Paradise_Island.ogg:system/media/audio/ringtones/Paradise_Island.ogg \
-	$(local_path)/newwavelabs/Road_Trip.ogg:system/media/audio/ringtones/Road_Trip.ogg \
-	$(local_path)/newwavelabs/Shes_All_That.ogg:system/media/audio/ringtones/Shes_All_That.ogg \
-	$(local_path)/newwavelabs/Steppin_Out.ogg:system/media/audio/ringtones/Steppin_Out.ogg \
-	$(local_path)/newwavelabs/Third_Eye.ogg:system/media/audio/ringtones/Third_Eye.ogg \
-	$(local_path)/newwavelabs/Thunderfoot.ogg:system/media/audio/ringtones/Thunderfoot.ogg \
-	$(local_path)/notifications/moonbeam.ogg:system/media/audio/notifications/moonbeam.ogg \
-	$(local_path)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
-	$(local_path)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
-	$(local_path)/notifications/tweeters.ogg:system/media/audio/notifications/tweeters.ogg
+	$(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
+	$(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
+	$(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
+	$(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \
+	$(LOCAL_PATH)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \
+	$(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
+	$(LOCAL_PATH)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \
+	$(LOCAL_PATH)/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \
+	$(LOCAL_PATH)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \
+	$(LOCAL_PATH)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \
+	$(LOCAL_PATH)/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \
+	$(LOCAL_PATH)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \
+	$(LOCAL_PATH)/newwavelabs/BentleyDubs.ogg:system/media/audio/ringtones/BentleyDubs.ogg \
+	$(LOCAL_PATH)/newwavelabs/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \
+	$(LOCAL_PATH)/newwavelabs/CaribbeanIce.ogg:system/media/audio/ringtones/CaribbeanIce.ogg \
+	$(LOCAL_PATH)/newwavelabs/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \
+	$(LOCAL_PATH)/newwavelabs/EtherShake.ogg:system/media/audio/ringtones/EtherShake.ogg \
+	$(LOCAL_PATH)/newwavelabs/FriendlyGhost.ogg:system/media/audio/ringtones/FriendlyGhost.ogg \
+	$(LOCAL_PATH)/newwavelabs/GameOverGuitar.ogg:system/media/audio/ringtones/GameOverGuitar.ogg \
+	$(LOCAL_PATH)/newwavelabs/Growl.ogg:system/media/audio/ringtones/Growl.ogg \
+	$(LOCAL_PATH)/newwavelabs/InsertCoin.ogg:system/media/audio/ringtones/InsertCoin.ogg \
+	$(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \
+	$(LOCAL_PATH)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \
+	$(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \
+	$(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \
+	$(LOCAL_PATH)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \
+	$(LOCAL_PATH)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \
+	$(LOCAL_PATH)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \
+	$(LOCAL_PATH)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \
+	$(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \
+	$(LOCAL_PATH)/newwavelabs/RomancingTheTone.ogg:system/media/audio/ringtones/RomancingTheTone.ogg \
+	$(LOCAL_PATH)/newwavelabs/SitarVsSitar.ogg:system/media/audio/ringtones/SitarVsSitar.ogg \
+	$(LOCAL_PATH)/newwavelabs/SpringyJalopy.ogg:system/media/audio/ringtones/SpringyJalopy.ogg \
+	$(LOCAL_PATH)/newwavelabs/Terminated.ogg:system/media/audio/ringtones/Terminated.ogg \
+	$(LOCAL_PATH)/newwavelabs/TwirlAway.ogg:system/media/audio/ringtones/TwirlAway.ogg \
+	$(LOCAL_PATH)/newwavelabs/VeryAlarmed.ogg:system/media/audio/ringtones/VeryAlarmed.ogg \
+	$(LOCAL_PATH)/newwavelabs/World.ogg:system/media/audio/ringtones/World.ogg \
+	$(LOCAL_PATH)/newwavelabs/CaffeineSnake.ogg:system/media/audio/notifications/CaffeineSnake.ogg \
+	$(LOCAL_PATH)/newwavelabs/DearDeer.ogg:system/media/audio/notifications/DearDeer.ogg \
+	$(LOCAL_PATH)/newwavelabs/DontPanic.ogg:system/media/audio/notifications/DontPanic.ogg \
+	$(LOCAL_PATH)/newwavelabs/Highwire.ogg:system/media/audio/notifications/Highwire.ogg \
+	$(LOCAL_PATH)/newwavelabs/KzurbSonar.ogg:system/media/audio/notifications/KzurbSonar.ogg \
+	$(LOCAL_PATH)/newwavelabs/OnTheHunt.ogg:system/media/audio/notifications/OnTheHunt.ogg \
+	$(LOCAL_PATH)/newwavelabs/Voila.ogg:system/media/audio/notifications/Voila.ogg \
+	$(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
+	$(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
+	$(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
+	$(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
+	$(LOCAL_PATH)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/newwavelabs/CrazyDream.ogg:system/media/audio/ringtones/CrazyDream.ogg \
+	$(LOCAL_PATH)/newwavelabs/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg \
+	$(LOCAL_PATH)/newwavelabs/Big_Easy.ogg:system/media/audio/ringtones/Big_Easy.ogg \
+	$(LOCAL_PATH)/newwavelabs/Bollywood.ogg:system/media/audio/ringtones/Bollywood.ogg \
+	$(LOCAL_PATH)/newwavelabs/Cairo.ogg:system/media/audio/ringtones/Cairo.ogg \
+	$(LOCAL_PATH)/newwavelabs/Calypso_Steel.ogg:system/media/audio/ringtones/Calypso_Steel.ogg \
+	$(LOCAL_PATH)/newwavelabs/Champagne_Edition.ogg:system/media/audio/ringtones/Champagne_Edition.ogg \
+	$(LOCAL_PATH)/newwavelabs/Club_Cubano.ogg:system/media/audio/ringtones/Club_Cubano.ogg \
+	$(LOCAL_PATH)/newwavelabs/Eastern_Sky.ogg:system/media/audio/ringtones/Eastern_Sky.ogg \
+	$(LOCAL_PATH)/newwavelabs/Funk_Yall.ogg:system/media/audio/ringtones/Funk_Yall.ogg \
+	$(LOCAL_PATH)/newwavelabs/Savannah.ogg:system/media/audio/ringtones/Savannah.ogg \
+	$(LOCAL_PATH)/newwavelabs/Gimme_Mo_Town.ogg:system/media/audio/ringtones/Gimme_Mo_Town.ogg \
+	$(LOCAL_PATH)/newwavelabs/Glacial_Groove.ogg:system/media/audio/ringtones/Glacial_Groove.ogg \
+	$(LOCAL_PATH)/newwavelabs/Seville.ogg:system/media/audio/ringtones/Seville.ogg \
+	$(LOCAL_PATH)/newwavelabs/No_Limits.ogg:system/media/audio/ringtones/No_Limits.ogg \
+	$(LOCAL_PATH)/newwavelabs/Revelation.ogg:system/media/audio/ringtones/Revelation.ogg \
+	$(LOCAL_PATH)/newwavelabs/Paradise_Island.ogg:system/media/audio/ringtones/Paradise_Island.ogg \
+	$(LOCAL_PATH)/newwavelabs/Road_Trip.ogg:system/media/audio/ringtones/Road_Trip.ogg \
+	$(LOCAL_PATH)/newwavelabs/Shes_All_That.ogg:system/media/audio/ringtones/Shes_All_That.ogg \
+	$(LOCAL_PATH)/newwavelabs/Steppin_Out.ogg:system/media/audio/ringtones/Steppin_Out.ogg \
+	$(LOCAL_PATH)/newwavelabs/Third_Eye.ogg:system/media/audio/ringtones/Third_Eye.ogg \
+	$(LOCAL_PATH)/newwavelabs/Thunderfoot.ogg:system/media/audio/ringtones/Thunderfoot.ogg \
+	$(LOCAL_PATH)/notifications/moonbeam.ogg:system/media/audio/notifications/moonbeam.ogg \
+	$(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
+	$(LOCAL_PATH)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
+	$(LOCAL_PATH)/notifications/tweeters.ogg:system/media/audio/notifications/tweeters.ogg
 
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index 97e0e90..e3544ab 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -76,6 +76,12 @@
     CAMERA_MSG_COMPRESSED_IMAGE
 };
 
+// camera fatal errors
+enum {
+    CAMERA_ERROR_UKNOWN  = 1,
+    CAMERA_ERROR_SERVER_DIED = 100
+};
+
 class ICameraService;
 class ICamera;
 class Surface;
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index a72d2c9..0aa77ff 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -312,7 +312,7 @@
 
 void Camera::binderDied(const wp<IBinder>& who) {
     LOGW("ICamera died");
-    notifyCallback(CAMERA_MSG_ERROR, DEAD_OBJECT, 0);
+    notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
 }
 
 void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index b5f5b37..5c0c55c 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -48,11 +48,9 @@
 
     private static class SpeechItem {
         public static final int TEXT = 0;
-        public static final int IPA = 1;
-        public static final int EARCON = 2;
-        public static final int SILENCE = 3;
-        public static final int TEXT_TO_FILE = 5;
-        public static final int IPA_TO_FILE = 6;
+        public static final int EARCON = 1;
+        public static final int SILENCE = 2;
+        public static final int TEXT_TO_FILE = 3;
         public String mText = null;
         public ArrayList<String> mParams = null;
         public int mType = TEXT;
@@ -327,28 +325,6 @@
     }
 
     /**
-     * Speaks the given IPA text using the specified queueing mode and parameters.
-     *
-     * @param ipaText
-     *            The IPA text that should be spoken
-     * @param queueMode
-     *            0 for no queue (interrupts all previous utterances), 1 for
-     *            queued
-     * @param params
-     *            An ArrayList of parameters. This is not implemented for all
-     *            engines.
-     */
-    private void speakIpa(String ipaText, int queueMode, ArrayList<String> params) {
-        if (queueMode == 0) {
-            stop();
-        }
-        mSpeechQueue.add(new SpeechItem(ipaText, params, SpeechItem.IPA));
-        if (!mIsSpeaking) {
-            processSpeechQueue();
-        }
-    }
-
-    /**
      * Plays the earcon using the specified queueing mode and parameters.
      *
      * @param earcon
@@ -617,8 +593,6 @@
                 } else if (currentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) {
                     synthToFileInternalOnly(currentSpeechItem.mText,
                             currentSpeechItem.mParams, currentSpeechItem.mFilename);
-                } else if (currentSpeechItem.mType == SpeechItem.IPA) {
-                    // TODO Implement IPA support
                 } else {
                     // This is either silence or an earcon that was missing
                     silence(currentSpeechItem.mDuration);
@@ -714,51 +688,6 @@
         return true;
     }
 
-    /**
-     * Synthesizes the given IPA text to a file using the specified parameters.
-     *
-     * @param ipaText
-     *            The String of IPA text that should be synthesized
-     * @param params
-     *            An ArrayList of parameters. The first element of this array
-     *            controls the type of voice to use.
-     * @param filename
-     *            The string that gives the full output filename; it should be
-     *            something like "/sdcard/myappsounds/mysound.wav".
-     * @return A boolean that indicates if the synthesis succeeded
-     */
-    private boolean synthesizeIpaToFile(String ipaText, ArrayList<String> params,
-            String filename, boolean calledFromApi) {
-        // Only stop everything if this is a call made by an outside app trying
-        // to
-        // use the API. Do NOT stop if this is a call from within the service as
-        // clearing the speech queue here would be a mistake.
-        if (calledFromApi) {
-            stop();
-        }
-        Log.i("TTS", "Synthesizing IPA to " + filename);
-        boolean synthAvailable = false;
-        try {
-            synthAvailable = synthesizerLock.tryLock();
-            if (!synthAvailable) {
-                return false;
-            }
-            // Don't allow a filename that is too long
-            if (filename.length() > MAX_FILENAME_LENGTH) {
-                return false;
-            }
-            // TODO: Add nativeSynth.synthesizeIpaToFile(text, filename);
-        } finally {
-            // This check is needed because finally will always run; even if the
-            // method returns somewhere in the try block.
-            if (synthAvailable) {
-                synthesizerLock.unlock();
-            }
-        }
-        Log.i("TTS", "Completed synthesis for " + filename);
-        return true;
-    }
-
     @Override
     public IBinder onBind(Intent intent) {
         if (ACTION.equals(intent.getAction())) {
@@ -805,27 +734,6 @@
         }
 
         /**
-         * Speaks the given IPA text using the specified queueing mode and
-         * parameters.
-         *
-         * @param ipaText
-         *            The IPA text that should be spoken
-         * @param queueMode
-         *            0 for no queue (interrupts all previous utterances), 1 for
-         *            queued
-         * @param params
-         *            An ArrayList of parameters. The first element of this
-         *            array controls the type of voice to use.
-         */
-        public void speakIpa(String ipaText, int queueMode, String[] params) {
-            ArrayList<String> speakingParams = new ArrayList<String>();
-            if (params != null) {
-                speakingParams = new ArrayList<String>(Arrays.asList(params));
-            }
-            mSelf.speakIpa(ipaText, queueMode, speakingParams);
-        }
-
-        /**
          * Plays the earcon using the specified queueing mode and parameters.
          *
          * @param earcon
@@ -1014,28 +922,6 @@
             return mSelf.synthesizeToFile(text, speakingParams, filename);
         }
 
-        /**
-         * Synthesizes the given IPA text to a file using the specified
-         * parameters.
-         *
-         * @param ipaText
-         *            The String of IPA text that should be synthesized
-         * @param params
-         *            An ArrayList of parameters. The first element of this
-         *            array controls the type of voice to use.
-         * @param filename
-         *            The string that gives the full output filename; it should
-         *            be something like "/sdcard/myappsounds/mysound.wav".
-         * @return A boolean that indicates if the synthesis succeeded
-         */
-        public boolean synthesizeIpaToFile(String ipaText, String[] params,
-                String filename) {
-            ArrayList<String> speakingParams = new ArrayList<String>();
-            if (params != null) {
-                speakingParams = new ArrayList<String>(Arrays.asList(params));
-            }
-            return mSelf.synthesizeIpaToFile(ipaText, speakingParams, filename, true);
-        }
     };
 
 }
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 953e401..7977d1f 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -81,6 +81,7 @@
     private static final int MSG_RUN_BACKUP = 1;
     private static final int MSG_RUN_FULL_BACKUP = 2;
     private static final int MSG_RUN_RESTORE = 3;
+    private static final int MSG_RUN_CLEAR = 4;
 
     // Timeout interval for deciding that a bind or clear-data has taken too long
     static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -148,6 +149,16 @@
         }
     }
 
+    private class ClearParams {
+        public IBackupTransport transport;
+        public PackageInfo packageInfo;
+
+        ClearParams(IBackupTransport _transport, PackageInfo _info) {
+            transport = _transport;
+            packageInfo = _info;
+        }
+    }
+
     // Where we keep our journal files and other bookkeeping
     private File mBaseStateDir;
     private File mDataDir;
@@ -386,6 +397,13 @@
                 (new PerformRestoreThread(params.transport, params.observer, params.token)).start();
                 break;
             }
+
+            case MSG_RUN_CLEAR:
+            {
+                ClearParams params = (ClearParams)msg.obj;
+                (new PerformClearThread(params.transport, params.packageInfo)).start();
+                break;
+            }
             }
         }
     }
@@ -925,6 +943,15 @@
                         mPackageManager, agentPackages);
                 processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind()));
 
+                // Verify that the backup set includes metadata.  If not, we can't do
+                // signature/version verification etc, so we simply do not proceed with
+                // the restore operation.
+                Metadata pmMeta = pmAgent.getRestoredMetadata(packageName);
+                if (pmMeta == null) {
+                    Log.i(TAG, "No restore metadata available, so not restoring settings");
+                    return;
+                }
+
                 int count = 0;
                 for (;;) {
                     packageName = mTransport.nextRestorePackage();
@@ -1071,6 +1098,37 @@
         }
     }
 
+    class PerformClearThread extends Thread {
+        IBackupTransport mTransport;
+        PackageInfo mPackage;
+
+        PerformClearThread(IBackupTransport transport, PackageInfo packageInfo) {
+            mTransport = transport;
+            mPackage = packageInfo;
+        }
+
+        @Override
+        public void run() {
+            try {
+                // Clear the on-device backup state to ensure a full backup next time
+                File stateDir = new File(mBaseStateDir, mTransport.transportDirName());
+                File stateFile = new File(stateDir, mPackage.packageName);
+                stateFile.delete();
+
+                // Tell the transport to remove all the persistent storage for the app
+                mTransport.clearBackupData(mPackage);
+            } catch (RemoteException e) {
+                // can't happen; the transport is local
+            } finally {
+                try {
+                    mTransport.finishBackup();
+                } catch (RemoteException e) {
+                    // can't happen; the transport is local
+                }
+            }
+        }
+    }
+
 
     // ----- IBackupManager binder interface -----
 
@@ -1142,6 +1200,52 @@
         }
     }
 
+    // Clear the given package's backup data from the current transport
+    public void clearBackupData(String packageName) {
+        if (DEBUG) Log.v(TAG, "clearBackupData() of " + packageName);
+        PackageInfo info;
+        try {
+            info = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, "No such package '" + packageName + "' - not clearing backup data");
+            return;
+        }
+
+        // If the caller does not hold the BACKUP permission, it can only request a
+        // wipe of its own backed-up data.
+        HashSet<ApplicationInfo> apps;
+        if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
+                Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
+            apps = mBackupParticipants.get(Binder.getCallingUid());
+        } else {
+            // a caller with full permission can ask to back up any participating app
+            // !!! TODO: allow data-clear of ANY app?
+            if (DEBUG) Log.v(TAG, "Privileged caller, allowing clear of other apps");
+            apps = new HashSet<ApplicationInfo>();
+            int N = mBackupParticipants.size();
+            for (int i = 0; i < N; i++) {
+                HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
+                if (s != null) {
+                    apps.addAll(s);
+                }
+            }
+        }
+
+        // now find the given package in the set of candidate apps
+        for (ApplicationInfo app : apps) {
+            if (app.packageName.equals(packageName)) {
+                if (DEBUG) Log.v(TAG, "Found the app - running clear process");
+                // found it; fire off the clear request
+                synchronized (mQueueLock) {
+                    Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR,
+                            new ClearParams(getTransport(mCurrentTransport), info));
+                    mBackupHandler.sendMessage(msg);
+                }
+                break;
+            }
+        }
+    }
+
     // Run a backup pass immediately for any applications that have declared
     // that they have pending updates.
     public void backupNow() throws RemoteException {
@@ -1183,7 +1287,8 @@
 
     // Report the name of the currently active transport
     public String getCurrentTransport() {
-        mContext.enforceCallingPermission("android.permission.BACKUP", "getCurrentTransport");
+        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+                "getCurrentTransport");
         Log.v(TAG, "... getCurrentTransport() returning " + mCurrentTransport);
         return mCurrentTransport;
     }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 384d334..5b48ab5 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -1921,7 +1921,7 @@
     
     private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
         boolean performed = false;
-        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
+        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
             String path = pkg.mScanPath;
             int ret = 0;
             try {
@@ -5808,24 +5808,15 @@
                     // Check to see if its a disabled system app
                     PackageSetting ps = mDisabledSysPackages.get(name);
                     if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
-                        // Could be a replaced system package
-                        // Note that if the user replaced a system app, the user has to physically
-                        // delete the new one in order to revert to the system app. So even
-                        // if the user updated the system app via an update, the user still
-                        // has to delete the one installed in the data partition in order to pick up the
-                        // new system package.
+                        // This is an updated system app with versions in both system
+                        // and data partition. Just let the most recent version
+                        // take precedence.
                         return p;
-                    } else if ((p.pkg != null) && (p.pkg.applicationInfo != null) &&
-                                ((p.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
-                        // Check for non-system apps
+                    } else if ((p.pkg != null) && (p.pkg.applicationInfo != null)) {
+                        // Let the app continue with previous uid if code path changes.
                         reportSettingsProblem(Log.WARN,
                                 "Package " + name + " codePath changed from " + p.codePath
                                 + " to " + codePath + "; Retaining data and using new code");
-                    } else {
-                        reportSettingsProblem(Log.WARN,
-                                "Package " + name + " codePath changed from " + p.codePath
-                                + " to " + codePath + "; replacing with new");
-                        p = null;
                     }
                 } else if (p.sharedUser != sharedUser) {
                     reportSettingsProblem(Log.WARN,
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 9d29272..c3818f5 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -96,6 +96,7 @@
      * Constants for the data connection activity:
      * physical link down/up
      */
+     private static final int DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE = 0;
      private static final int DATA_CONNECTION_ACTIVE_PH_LINK_DOWN = 1;
      private static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2;
 
@@ -832,7 +833,7 @@
         }
     }
 
-    private void onCdmaDataAttached() {
+    private void onCdmaDataDetached() {
         if (state == State.CONNECTED) {
             startNetStatPoll();
             phone.notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED);
@@ -852,6 +853,14 @@
         }
     }
 
+    private void writeEventLogCdmaDataDrop() {
+        CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
+        int bsid = (loc != null) ? loc.getBaseStationId() : -1;
+        EventLog.List val = new EventLog.List(bsid,
+                TelephonyManager.getDefault().getNetworkType());
+        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_DROP, val);
+    }
+
     protected void onDataStateChanged (AsyncResult ar) {
         ArrayList<DataCallState> dataCallStates = (ArrayList<DataCallState>)(ar.result);
 
@@ -863,24 +872,37 @@
         }
 
         if (state == State.CONNECTED) {
-            if (dataCallStates.get(0).active == DATA_CONNECTION_ACTIVE_PH_LINK_UP ) {
-                activity = Activity.NONE;
-                phone.notifyDataActivity();
-            } else if (dataCallStates.get(0).active == DATA_CONNECTION_ACTIVE_PH_LINK_DOWN ) {
-                activity = Activity.DORMANT;
-                phone.notifyDataActivity();
+            if (dataCallStates.size() >= 1) {
+                switch (dataCallStates.get(0).active) {
+                case DATA_CONNECTION_ACTIVE_PH_LINK_UP:
+                    Log.v(LOG_TAG, "onDataStateChanged: active=LINK_ACTIVE && CONNECTED, ignore");
+                    activity = Activity.NONE;
+                    phone.notifyDataActivity();
+                    break;
+                case DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE:
+                    Log.v(LOG_TAG,
+                    "onDataStateChanged active=LINK_INACTIVE && CONNECTED, disconnecting/cleanup");
+                    writeEventLogCdmaDataDrop();
+                    cleanUpConnection(true, null);
+                    break;
+                case DATA_CONNECTION_ACTIVE_PH_LINK_DOWN:
+                    Log.v(LOG_TAG, "onDataStateChanged active=LINK_DOWN && CONNECTED, dormant");
+                    activity = Activity.DORMANT;
+                    phone.notifyDataActivity();
+                    break;
+                default:
+                    Log.v(LOG_TAG, "onDataStateChanged: IGNORE unexpected DataCallState.active="
+                            + dataCallStates.get(0).active);
+                }
+            } else {
+                Log.v(LOG_TAG, "onDataStateChanged: network disconnected, clean up");
+                writeEventLogCdmaDataDrop();
+                cleanUpConnection(true, null);
             }
         } else {
-
-            CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
-            int bsid = (loc != null) ? loc.getBaseStationId() : -1;
-            EventLog.List val = new EventLog.List(bsid,
-                    TelephonyManager.getDefault().getNetworkType());
-            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_DROP, val);
-
-            cleanUpConnection(true, null);
+            // TODO: Do we need to do anything?
+            Log.i(LOG_TAG, "onDataStateChanged: not connected, state=" + state + " ignoring");
         }
-        Log.i(LOG_TAG, "Data connection has changed.");
     }
 
     String getInterfaceName() {
@@ -932,7 +954,7 @@
                 break;
 
             case EVENT_CDMA_DATA_DETACHED:
-                onCdmaDataAttached();
+                onCdmaDataDetached();
                 break;
 
             case EVENT_DATA_STATE_CHANGED:
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java b/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java
index 51e841c..7720041 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java
@@ -276,6 +276,7 @@
         Spannable s3 = new SpannableString(s1);
         s3.setSpan(new StyleSpan(0), 5, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
         TextPaint p = new TextPaint();
+        p.setFlags(p.getFlags() & ~p.DEV_KERN_TEXT_FLAG);
 
         for (int i = 0; i < 100; i++) {
             for (int j = 0; j < 3; j++) {