Merge change 5750 into donut

* changes:
  Add a new checkin server flag for Vending Machine client server ping frequency for pending downloads.
diff --git a/api/current.xml b/api/current.xml
index 673d053..1287f59 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -3419,39 +3419,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad23"
- type="int"
- transient="false"
- volatile="false"
- value="16843401"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad24"
- type="int"
- transient="false"
- volatile="false"
- value="16843400"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad25"
- type="int"
- transient="false"
- volatile="false"
- value="16843399"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="donut_resource_pad3"
  type="int"
  transient="false"
@@ -6730,6 +6697,17 @@
  visibility="public"
 >
 </field>
+<field name="progressBarStyleInverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843399"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="progressBarStyleLarge"
  type="int"
  transient="false"
@@ -6741,6 +6719,17 @@
  visibility="public"
 >
 </field>
+<field name="progressBarStyleLargeInverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843401"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="progressBarStyleSmall"
  type="int"
  transient="false"
@@ -6752,6 +6741,17 @@
  visibility="public"
 >
 </field>
+<field name="progressBarStyleSmallInverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843400"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="progressBarStyleSmallTitle"
  type="int"
  transient="false"
@@ -15156,6 +15156,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_ProgressBar_Inverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973915"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ProgressBar_Large"
  type="int"
  transient="false"
@@ -15167,6 +15178,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_ProgressBar_Large_Inverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973916"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ProgressBar_Small"
  type="int"
  transient="false"
@@ -15178,6 +15200,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_ProgressBar_Small_Inverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973917"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_RatingBar"
  type="int"
  transient="false"
@@ -15409,39 +15442,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad20"
- type="int"
- transient="false"
- volatile="false"
- value="16973917"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad21"
- type="int"
- transient="false"
- volatile="false"
- value="16973916"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad22"
- type="int"
- transient="false"
- volatile="false"
- value="16973915"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="donut_resource_pad3"
  type="int"
  transient="false"
@@ -31346,6 +31346,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_BATTERY_OKAY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.BATTERY_OKAY&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_BOOT_COMPLETED"
  type="java.lang.String"
  transient="false"
@@ -56678,6 +56689,47 @@
 </package>
 <package name="android.graphics.drawable"
 >
+<interface name="Animatable"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="isRunning"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="start"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="stop"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
 <class name="AnimationDrawable"
  extends="android.graphics.drawable.DrawableContainer"
  abstract="false"
@@ -56686,6 +56738,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.graphics.drawable.Animatable">
+</implements>
 <implements name="java.lang.Runnable">
 </implements>
 <constructor name="AnimationDrawable"
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 105d4d2..022fe5a 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -410,11 +410,14 @@
 // pass the buffered ISurface to the camera service
 status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
 {
-    LOGD("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
+    LOGD("setPreviewDisplay(%p) (pid %d)",
+         ((surface == NULL) ? NULL : surface.get()), getCallingPid());
     Mutex::Autolock lock(mLock);
     status_t result = checkPid();
     if (result != NO_ERROR) return result;
+
     Mutex::Autolock surfaceLock(mSurfaceLock);
+    result = NO_ERROR;
     // asBinder() is safe on NULL (returns NULL)
     if (surface->asBinder() != mSurface->asBinder()) {
         if (mSurface != 0 && !mUseOverlay) {
@@ -422,8 +425,17 @@
             mSurface->unregisterBuffers();
         }
         mSurface = surface;
+        // If preview has been already started, set overlay or register preview
+        // buffers now.
+        if (mHardware->previewEnabled()) {
+            if (mUseOverlay) {
+                result = setOverlay();
+            } else if (mSurface != 0) {
+                result = registerPreviewBuffers();
+            }
+        }
     }
-    return NO_ERROR;
+    return result;
 }
 
 // set the preview callback flag to affect how the received frames from
@@ -436,7 +448,7 @@
     mPreviewCallbackFlag = callback_flag;
 }
 
-// start preview mode, must call setPreviewDisplay first
+// start preview mode
 status_t CameraService::Client::startCameraMode(camera_mode mode)
 {
     int callingPid = getCallingPid();
@@ -456,16 +468,18 @@
         return INVALID_OPERATION;
     }
 
-    if (mSurface == 0) {
-        LOGE("setPreviewDisplay must be called before startCameraMode!");
-        return INVALID_OPERATION;
-    }
-
     switch(mode) {
     case CAMERA_RECORDING_MODE:
+        if (mSurface == 0) {
+            LOGE("setPreviewDisplay must be called before startRecordingMode.");
+            return INVALID_OPERATION;
+        }
         return startRecordingMode();
 
     default: // CAMERA_PREVIEW_MODE
+        if (mSurface == 0) {
+            LOGD("mSurface is not set yet.");
+        }
         return startPreviewMode();
     }
 }
@@ -498,6 +512,62 @@
     return ret;
 }
 
+status_t CameraService::Client::setOverlay()
+{
+    LOGD("setOverlay");
+    int w, h;
+    CameraParameters params(mHardware->getParameters());
+    params.getPreviewSize(&w, &h);
+
+    const char *format = params.getPreviewFormat();
+    int fmt;
+    if (!strcmp(format, "yuv422i"))
+        fmt = OVERLAY_FORMAT_YCbCr_422_I;
+    else if (!strcmp(format, "rgb565"))
+        fmt = OVERLAY_FORMAT_RGB_565;
+    else {
+        LOGE("Invalid preview format for overlays");
+        return -EINVAL;
+    }
+
+    status_t ret = NO_ERROR;
+    if (mSurface != 0) {
+        sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
+        ret = mHardware->setOverlay(new Overlay(ref));
+    } else {
+        ret = mHardware->setOverlay(NULL);
+    }
+    if (ret != NO_ERROR) {
+        LOGE("mHardware->setOverlay() failed with status %d\n", ret);
+    }
+    return ret;
+}
+
+status_t CameraService::Client::registerPreviewBuffers()
+{
+    int w, h;
+    CameraParameters params(mHardware->getParameters());
+    params.getPreviewSize(&w, &h);
+
+    uint32_t transform = 0;
+    if (params.getOrientation() ==
+        CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
+      LOGV("portrait mode");
+      transform = ISurface::BufferHeap::ROT_90;
+    }
+    ISurface::BufferHeap buffers(w, h, w, h,
+                                 PIXEL_FORMAT_YCbCr_420_SP,
+                                 transform,
+                                 0,
+                                 mHardware->getPreviewHeap());
+
+    status_t ret = mSurface->registerBuffers(buffers);
+    if (ret != NO_ERROR) {
+        LOGE("registerBuffers failed with status %d", ret);
+    }
+    return ret;
+}
+
 status_t CameraService::Client::startPreviewMode()
 {
     LOGD("startPreviewMode (pid %d)", getCallingPid());
@@ -511,55 +581,24 @@
 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
     debug_frame_cnt = 0;
 #endif
-    status_t ret = UNKNOWN_ERROR;
-    int w, h;
-    CameraParameters params(mHardware->getParameters());
-    params.getPreviewSize(&w, &h);
+    status_t ret = NO_ERROR;
 
     if (mUseOverlay) {
-        const char *format = params.getPreviewFormat();
-        int fmt;
-        LOGD("Use Overlays");
-        if (!strcmp(format, "yuv422i"))
-            fmt = OVERLAY_FORMAT_YCbCr_422_I;
-        else if (!strcmp(format, "rgb565"))
-            fmt = OVERLAY_FORMAT_RGB_565;
-        else {
-            LOGE("Invalid preview format for overlays");
-            return -EINVAL;
+        // If preview display has been set, set overlay now.
+        if (mSurface != 0) {
+            ret = setOverlay();
         }
-        sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
-        ret = mHardware->setOverlay(new Overlay(ref));
-        if (ret != NO_ERROR) {
-            LOGE("mHardware->setOverlay() failed with status %d\n", ret);
-            return ret;
-        }
+        if (ret != NO_ERROR) return ret;
         ret = mHardware->startPreview(NULL, mCameraService.get());
-        if (ret != NO_ERROR)
-            LOGE("mHardware->startPreview() failed with status %d\n", ret);
-
     } else {
         ret = mHardware->startPreview(previewCallback,
                                       mCameraService.get());
-        if (ret == NO_ERROR) {
-
-            mSurface->unregisterBuffers();
-
-            uint32_t transform = 0;
-            if (params.getOrientation() ==
-                CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
-              LOGV("portrait mode");
-              transform = ISurface::BufferHeap::ROT_90;
-            }
-            ISurface::BufferHeap buffers(w, h, w, h,
-                                         PIXEL_FORMAT_YCbCr_420_SP,
-                                         transform,
-                                         0,
-                                         mHardware->getPreviewHeap());
-
-            mSurface->registerBuffers(buffers);
-        } else {
-          LOGE("mHardware->startPreview() failed with status %d", ret);
+        if (ret != NO_ERROR) return ret;
+        // If preview display has been set, register preview buffers now.
+        if (mSurface != 0) {
+           // Unregister here because the surface registered with raw heap.
+           mSurface->unregisterBuffers();
+           ret = registerPreviewBuffers();
         }
     }
     return ret;
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 8b8b54c..0f07673 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -157,6 +157,8 @@
         status_t                startCameraMode(camera_mode mode);
         status_t                startPreviewMode();
         status_t                startRecordingMode();
+        status_t                setOverlay();
+        status_t                registerPreviewBuffers();
 
         // Ensures atomicity among the public methods
         mutable     Mutex                       mLock;
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 6fe4896..44d1eaa 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -34,6 +34,7 @@
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Animatable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
@@ -422,11 +423,11 @@
         if (working) {
             mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
                     null, null, mWorkingSpinner, null);
-//            mWorkingSpinner.start();
+            ((Animatable) mWorkingSpinner).start();
         } else {
             mSearchAutoComplete.setCompoundDrawablesWithIntrinsicBounds(
                     null, null, null, null);
-//            mWorkingSpinner.stop();
+            ((Animatable) mWorkingSpinner).stop();
         }
     }
     
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6fe5506..6b723bc 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1290,6 +1290,13 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW";
     /**
+     * Broadcast Action:  Indicates the battery is now okay after being low.
+     * This will be sent after {@link #ACTION_BATTERY_LOW} once the battery has
+     * gone back up to an okay state.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_BATTERY_OKAY = "android.intent.action.BATTERY_OKAY";
+    /**
      * Broadcast Action:  External power has been connected to the device.
      * This is intended for applications that wish to register specifically to this notification.
      * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 09fbc97..3ce951f 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -155,7 +155,11 @@
      * @throws IOException if the method fails.
      */
     public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
-        setPreviewDisplay(holder.getSurface());
+        if (holder != null) {
+            setPreviewDisplay(holder.getSurface());
+        } else {
+            setPreviewDisplay((Surface)null);
+        }
     }
 
     private native final void setPreviewDisplay(Surface surface);
diff --git a/core/java/android/net/http/RequestHandle.java b/core/java/android/net/http/RequestHandle.java
index c4ee5b0..6a97951 100644
--- a/core/java/android/net/http/RequestHandle.java
+++ b/core/java/android/net/http/RequestHandle.java
@@ -159,11 +159,11 @@
             e.printStackTrace();
         }
 
-        // update the "cookie" header based on the redirected url
-        mHeaders.remove("cookie");
+        // update the "Cookie" header based on the redirected url
+        mHeaders.remove("Cookie");
         String cookie = CookieManager.getInstance().getCookie(mUri);
         if (cookie != null && cookie.length() > 0) {
-            mHeaders.put("cookie", cookie);
+            mHeaders.put("Cookie", cookie);
         }
 
         if ((statusCode == 302 || statusCode == 303) && mMethod.equals("POST")) {
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 51d1951..bc7b5be 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -344,7 +344,10 @@
                 // Check if file exists with a FileInputStream
                 FileInputStream stream = new FileInputStream(imagePath);
                 try {
-                    return insertImage(cr, BitmapFactory.decodeFile(imagePath), name, description);
+                    Bitmap bm = BitmapFactory.decodeFile(imagePath);
+                    String ret = insertImage(cr, bm, name, description);
+                    bm.recycle();
+                    return ret;
                 } finally {
                     try {
                         stream.close();
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 6f1b160..66ab021 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -364,7 +364,7 @@
         String cookie = CookieManager.getInstance().getCookie(
                 mListener.getWebAddress());
         if (cookie != null && cookie.length() > 0) {
-            mHeaders.put("cookie", cookie);
+            mHeaders.put("Cookie", cookie);
         }
     }
 }
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 441414a..2c9e71e 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -30,6 +30,7 @@
 import android.graphics.drawable.LayerDrawable;
 import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.StateListDrawable;
+import android.graphics.drawable.Animatable;
 import android.graphics.drawable.shapes.RoundRectShape;
 import android.graphics.drawable.shapes.Shape;
 import android.util.AttributeSet;
@@ -683,7 +684,7 @@
             return;
         }
 
-        if (mIndeterminateDrawable instanceof AnimationDrawable) {
+        if (mIndeterminateDrawable instanceof Animatable) {
             mShouldStartAnimationDrawable = true;
             mAnimation = null;
         } else {
@@ -708,8 +709,8 @@
     void stopAnimation() {
         mAnimation = null;
         mTransformation = null;
-        if (mIndeterminateDrawable instanceof AnimationDrawable) {
-            ((AnimationDrawable) mIndeterminateDrawable).stop();
+        if (mIndeterminateDrawable instanceof Animatable) {
+            ((Animatable) mIndeterminateDrawable).stop();
             mShouldStartAnimationDrawable = false;
         }
     }
@@ -818,8 +819,8 @@
             }
             d.draw(canvas);
             canvas.restore();
-            if (mShouldStartAnimationDrawable && d instanceof AnimationDrawable) {
-                ((AnimationDrawable) d).start();
+            if (mShouldStartAnimationDrawable && d instanceof Animatable) {
+                ((Animatable) d).start();
                 mShouldStartAnimationDrawable = false;
             }
         }
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 8e48b38..3dcc09f 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -171,6 +171,10 @@
     // VM pointer will be NULL if object is released
     Mutex::Autolock _l(mLock);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (mCameraJObjectWeak == NULL) {
+        LOGW("callback on dead camera object");
+        return;
+    }
 
     // return data based on callback type
     switch(msgType) {
@@ -262,7 +266,10 @@
     sp<Camera> camera = get_native_camera(env, thiz, NULL);
     if (camera == 0) return;
 
-    sp<Surface> surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
+    sp<Surface> surface = NULL;
+    if (jSurface != NULL) {
+        surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
+    }
     if (camera->setPreviewDisplay(surface) != NO_ERROR) {
         jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
     }
diff --git a/core/res/res/drawable/progress_large.xml b/core/res/res/drawable/progress_large.xml
index 4669104..4f016bc 100644
--- a/core/res/res/drawable/progress_large.xml
+++ b/core/res/res/drawable/progress_large.xml
@@ -1,45 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
 -->
-
-    
-<rotate xmlns:android="http://schemas.android.com/apk/res/android"
-        android:pivotX="50%" android:pivotY="50%"
-        android:fromDegrees="0" android:toDegrees="360">
-        
-    <shape
-            android:shape="ring"
-            android:innerRadiusRatio="3"
-            android:thicknessRatio="8"
-            android:useLevel="false">
-
-        <size
-                android:width="76dip"
-                android:height="76dip"
-        />
-        
-        <gradient
-                android:type="sweep"
-                android:useLevel="false"
-                android:startColor="#4c737373"
-                android:centerColor="#4c737373"
-                android:centerY="0.50"
-                android:endColor="#ffffd300"
-        />
-        
-    </shape>
-    
-</rotate>
-    
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/spinner_black_76"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:framesCount="12"
+    android:frameDuration="100" />
diff --git a/core/res/res/drawable/progress_large_white.xml b/core/res/res/drawable/progress_large_white.xml
new file mode 100644
index 0000000..c690ed4
--- /dev/null
+++ b/core/res/res/drawable/progress_large_white.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/spinner_white_76"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:framesCount="12"
+    android:frameDuration="100" />
diff --git a/core/res/res/drawable/progress_medium.xml b/core/res/res/drawable/progress_medium.xml
index 92aebb5..eb1bd50 100644
--- a/core/res/res/drawable/progress_medium.xml
+++ b/core/res/res/drawable/progress_medium.xml
@@ -1,43 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
 -->
-
-<rotate xmlns:android="http://schemas.android.com/apk/res/android"
-        android:pivotX="50%" android:pivotY="50%"
-        android:fromDegrees="0" android:toDegrees="360">
-        
-    <shape
-            android:shape="ring"
-            android:innerRadiusRatio="3"
-            android:thicknessRatio="8"
-            android:useLevel="false">
-
-        <size
-                android:width="48dip"
-                android:height="48dip"
-        />
-        
-        <gradient
-                android:type="sweep"
-                android:useLevel="false"
-                android:startColor="#4c737373"
-                android:centerColor="#4c737373"
-                android:centerY="0.50"
-                android:endColor="#ffffd300"
-        />
-        
-    </shape>
-    
-</rotate>
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/spinner_black_48"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:framesCount="12"
+    android:frameDuration="100" />
diff --git a/core/res/res/drawable/progress_medium_white.xml b/core/res/res/drawable/progress_medium_white.xml
new file mode 100644
index 0000000..b4f9b31
--- /dev/null
+++ b/core/res/res/drawable/progress_medium_white.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/spinner_white_48"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:framesCount="12"
+    android:frameDuration="100" />
diff --git a/core/res/res/drawable/progress_small.xml b/core/res/res/drawable/progress_small.xml
index e5b0021..e0ee5e4 100644
--- a/core/res/res/drawable/progress_small.xml
+++ b/core/res/res/drawable/progress_small.xml
@@ -1,45 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
 -->
-
- 
-<rotate xmlns:android="http://schemas.android.com/apk/res/android"
-        android:pivotX="50%" android:pivotY="50%"
-        android:fromDegrees="0" android:toDegrees="360">
-
-    <!-- An extra pixel is added on both ratios for stroke -->        
-    <shape
-            android:shape="ring"
-            android:innerRadiusRatio="3.2"
-            android:thicknessRatio="5.333"
-            android:useLevel="false">
-
-        <size
-                android:width="16dip"
-                android:height="16dip"
-        />
-        
-        <gradient
-                android:type="sweep"
-                android:useLevel="false"
-                android:startColor="#4c737373"
-                android:centerColor="#4c737373"
-                android:centerY="0.50"
-                android:endColor="#ffffd300"
-        />
-        
-    </shape>
-    
-</rotate>
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/spinner_black_16"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:framesCount="12"
+    android:frameDuration="100" />
diff --git a/core/res/res/drawable/progress_small_titlebar.xml b/core/res/res/drawable/progress_small_titlebar.xml
index cf8e41cb..8cfba86 100644
--- a/core/res/res/drawable/progress_small_titlebar.xml
+++ b/core/res/res/drawable/progress_small_titlebar.xml
@@ -1,45 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
 -->
-
- 
-<rotate xmlns:android="http://schemas.android.com/apk/res/android"
-        android:pivotX="50%" android:pivotY="50%"
-        android:fromDegrees="0" android:toDegrees="360">
-
-    <!-- An extra pixel is added on both ratios for stroke -->        
-    <shape
-            android:shape="ring"
-            android:innerRadiusRatio="3.2"
-            android:thicknessRatio="5.333"
-            android:useLevel="false">
-
-        <size
-                android:width="16dip"
-                android:height="16dip"
-        />
-        
-        <gradient
-                android:type="sweep"
-                android:useLevel="false"
-                android:startColor="#ff666666"
-                android:centerColor="#ff666666"
-                android:centerY="0.50"
-                android:endColor="#ffffd300"
-        />
-        
-    </shape>
-    
-</rotate>
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/spinner_white_16"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:framesCount="12"
+    android:frameDuration="100" />
diff --git a/core/res/res/drawable/progress_small_white.xml b/core/res/res/drawable/progress_small_white.xml
new file mode 100644
index 0000000..8cfba86
--- /dev/null
+++ b/core/res/res/drawable/progress_small_white.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/spinner_white_16"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:framesCount="12"
+    android:frameDuration="100" />
diff --git a/core/res/res/drawable/spinner_black_16.png b/core/res/res/drawable/spinner_black_16.png
new file mode 100644
index 0000000..5ee33ce
--- /dev/null
+++ b/core/res/res/drawable/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable/spinner_black_48.png b/core/res/res/drawable/spinner_black_48.png
new file mode 100644
index 0000000..3a68192
--- /dev/null
+++ b/core/res/res/drawable/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable/spinner_black_76.png b/core/res/res/drawable/spinner_black_76.png
new file mode 100644
index 0000000..ec57460
--- /dev/null
+++ b/core/res/res/drawable/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable/spinner_white_16.png b/core/res/res/drawable/spinner_white_16.png
new file mode 100644
index 0000000..dd2e1fd
--- /dev/null
+++ b/core/res/res/drawable/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable/spinner_white_48.png b/core/res/res/drawable/spinner_white_48.png
new file mode 100644
index 0000000..d25a33e
--- /dev/null
+++ b/core/res/res/drawable/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable/spinner_white_76.png b/core/res/res/drawable/spinner_white_76.png
new file mode 100644
index 0000000..f53e8ff
--- /dev/null
+++ b/core/res/res/drawable/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d070107..3e93b02 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -350,6 +350,12 @@
         <attr name="progressBarStyleSmallTitle" format="reference" />
         <!-- Large ProgressBar style. This is a large circular progress bar. -->
         <attr name="progressBarStyleLarge" format="reference" />
+        <!-- Inverse ProgressBar style. This is a medium circular progress bar. -->
+        <attr name="progressBarStyleInverse" format="reference" />
+        <!-- Small inverse ProgressBar style. This is a small circular progress bar. -->
+        <attr name="progressBarStyleSmallInverse" format="reference" />
+        <!-- Large inverse ProgressBar style. This is a large circular progress bar. -->
+        <attr name="progressBarStyleLargeInverse" format="reference" /> 
         <!-- Default SeekBar style. -->
         <attr name="seekBarStyle" format="reference" />
         <!-- Default RatingBar style. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 14d8dbe..2121669 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1120,11 +1120,17 @@
   <public type="attr" name="smallScreens" />
   <public type="attr" name="normalScreens" />
   <public type="attr" name="largeScreens" />
+  <public type="attr" name="progressBarStyleInverse" />
+  <public type="attr" name="progressBarStyleSmallInverse" />
+  <public type="attr" name="progressBarStyleLargeInverse" /> 
 
   <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
 
   <public-padding type="id" name="donut_resource_pad" end="0x01020040" />
   
+  <public type="style" name="Widget.ProgressBar.Inverse" id="0x0103005b" />
+  <public type="style" name="Widget.ProgressBar.Large.Inverse" id="0x0103005c" />
+  <public type="style" name="Widget.ProgressBar.Small.Inverse" id="0x0103005d" /> 
   <public-padding type="style" name="donut_resource_pad" end="0x01030070" />
   
   <public-padding type="string" name="donut_resource_pad" end="0x01040030" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9f1ed40..1ce9c76 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1786,6 +1786,11 @@
     <!-- See EXTMEDIA_FORMAT.    This is the button text to format the sd card. -->
     <string name="extmedia_format_button_format">Format</string>
 
+    <!-- Title of notification shown when ADB is actively connected to the phone. -->
+    <string name="adb_active_notification_title">USB debugging connected</string>
+    <!-- Message of notification shown when ADB is actively connected to the phone. -->
+    <string name="adb_active_notification_message">A computer is connected to your phone.</string>
+    
     <!-- Used to replace %s in urls retreived from the signin server with locales.  For Some        -->
     <!-- devices we don't support all the locales we ship to and need to replace the '%s' with a    -->
     <!-- locale string based on mcc values.  By default (0-length string) we don't replace the %s   -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 648a7dd..7d235ec 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -243,7 +243,7 @@
 
     <style name="Widget.ProgressBar">
         <item name="android:indeterminateOnly">true</item>
-        <item name="android:indeterminateDrawable">@android:drawable/progress_medium</item>
+        <item name="android:indeterminateDrawable">@android:drawable/progress_medium_white</item>
         <item name="android:indeterminateBehavior">repeat</item>
         <item name="android:indeterminateDuration">3500</item>
         <item name="android:minWidth">48dip</item>
@@ -253,7 +253,7 @@
     </style>
 
     <style name="Widget.ProgressBar.Large">
-        <item name="android:indeterminateDrawable">@android:drawable/progress_large</item>
+        <item name="android:indeterminateDrawable">@android:drawable/progress_large_white</item>
         <item name="android:minWidth">76dip</item>
         <item name="android:maxWidth">76dip</item>
         <item name="android:minHeight">76dip</item>
@@ -261,13 +261,25 @@
     </style>
     
     <style name="Widget.ProgressBar.Small">
-        <item name="android:indeterminateDrawable">@android:drawable/progress_small</item>
+        <item name="android:indeterminateDrawable">@android:drawable/progress_small_white</item>
         <item name="android:minWidth">16dip</item>
         <item name="android:maxWidth">16dip</item>
         <item name="android:minHeight">16dip</item>
         <item name="android:maxHeight">16dip</item>
     </style>
 
+    <style name="Widget.ProgressBar.Inverse">
+        <item name="android:indeterminateDrawable">@android:drawable/progress_medium</item>
+    </style>
+
+    <style name="Widget.ProgressBar.Large.Inverse">
+        <item name="android:indeterminateDrawable">@android:drawable/progress_large</item>
+    </style>
+
+    <style name="Widget.ProgressBar.Small.Inverse">
+        <item name="android:indeterminateDrawable">@android:drawable/progress_small</item>
+    </style> 
+    
     <style name="Widget.ProgressBar.Small.Title">
         <item name="android:indeterminateDrawable">@android:drawable/progress_small_titlebar</item>
     </style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index f37d514..bd6e1df 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -154,6 +154,9 @@
         <item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small</item>
         <item name="progressBarStyleSmallTitle">@android:style/Widget.ProgressBar.Small.Title</item>
         <item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large</item>
+        <item name="progressBarStyleInverse">@android:style/Widget.ProgressBar.Inverse</item>
+		<item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small.Inverse</item>
+	    <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large.Inverse</item> 
         <item name="seekBarStyle">@android:style/Widget.SeekBar</item>
         <item name="ratingBarStyle">@android:style/Widget.RatingBar</item>
         <item name="ratingBarStyleIndicator">@android:style/Widget.RatingBar.Indicator</item>
@@ -233,6 +236,13 @@
         <item name="listViewStyle">@android:style/Widget.ListView.White</item>
         <item name="listDivider">@drawable/divider_horizontal_bright</item>
         <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item>
+        
+        <item name="progressBarStyle">@android:style/Widget.ProgressBar.Inverse</item>
+		<item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small.Inverse</item>
+		<item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large.Inverse</item>
+		<item name="progressBarStyleInverse">@android:style/Widget.ProgressBar</item>
+		<item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small</item>
+		<item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large</item> 
     </style>
     
     <!-- Variant of the light theme with no title bar -->
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 2b24ef2..778c903 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -57,7 +57,9 @@
         mBitmap = patch.mBitmap;
         mChunk = patch.mChunk;
         mSrcName = patch.mSrcName;
-        mPaint = new Paint(patch.mPaint);
+        if (patch.mPaint != null) {
+            mPaint = new Paint(patch.mPaint);
+        }
         validateNinePatchChunk(mBitmap.ni(), mChunk);
     }
 
@@ -120,7 +122,6 @@
     
     public native static boolean isNinePatchChunk(byte[] chunk);
 
-    private final Rect   mRect = new Rect();
     private final Bitmap mBitmap;
     private final byte[] mChunk;
     private Paint        mPaint;
diff --git a/graphics/java/android/graphics/drawable/Animatable.java b/graphics/java/android/graphics/drawable/Animatable.java
new file mode 100644
index 0000000..9dc62c3
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/Animatable.java
@@ -0,0 +1,39 @@
+/*
+ * 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.graphics.drawable;
+
+/**
+ * Interface that drawables suporting animations should implement.
+ */
+public interface Animatable {
+    /**
+     * Starts the drawable's animation.
+     */
+    void start();
+
+    /**
+     * Stops the drawable's animation.
+     */
+    void stop();
+
+    /**
+     * Indicates whether the animation is running.
+     * 
+     * @return True if the animation is running, false otherwise.
+     */
+    boolean isRunning();
+}
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index 08d295d..ac96f20 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -35,11 +35,14 @@
 /**
  * @hide
  */
-public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable {
+public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable,
+        Animatable {
+
     private AnimatedRotateState mState;
     private boolean mMutated;
     private float mCurrentDegrees;
     private float mIncrement;
+    private boolean mRunning;
 
     public AnimatedRotateDrawable() {
         this(null);
@@ -80,10 +83,24 @@
         drawable.draw(canvas);
 
         canvas.restoreToCount(saveCount);
-        
-        nextFrame();
     }
-    
+
+    public void start() {
+        if (!mRunning) {
+            mRunning = true;
+            nextFrame();
+        }
+    }
+
+    public void stop() {
+        mRunning = false;
+        unscheduleSelf(this);
+    }
+
+    public boolean isRunning() {
+        return mRunning;
+    }
+
     private void nextFrame() {
         unscheduleSelf(this);
         scheduleSelf(this, SystemClock.uptimeMillis() + mState.mFrameDuration);
@@ -96,8 +113,8 @@
         if (mCurrentDegrees > (360.0f - mIncrement)) {
             mCurrentDegrees = 0.0f;
         }
-        nextFrame();
         invalidateSelf();
+        nextFrame();
     }
     
     @Override
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index bab1703..68718c9 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -71,7 +71,7 @@
  * @attr ref android.R.styleable#AnimationDrawableItem_duration
  * @attr ref android.R.styleable#AnimationDrawableItem_drawable
  */
-public class AnimationDrawable extends DrawableContainer implements Runnable {
+public class AnimationDrawable extends DrawableContainer implements Runnable, Animatable {
     private final AnimationState mAnimationState;
     private int mCurFrame = -1;
     private boolean mMutated;
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index bb22dab..a481ce7 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -149,21 +149,21 @@
 status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
 {
     LOGV("setPreviewDisplay");
-    if (surface == 0) {
-        LOGE("app passed NULL surface");
-        return NO_INIT;
-    }
     sp <ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
-    return c->setPreviewDisplay(surface->getISurface());
+    if (surface != 0) {
+        return c->setPreviewDisplay(surface->getISurface());
+    } else {
+        LOGD("app passed NULL surface");
+        return c->setPreviewDisplay(0);
+    }
 }
 
 status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
 {
     LOGV("setPreviewDisplay");
     if (surface == 0) {
-        LOGE("app passed NULL surface");
-        return NO_INIT;
+        LOGD("app passed NULL surface");
     }
     sp <ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
@@ -171,7 +171,7 @@
 }
 
 
-// start preview mode, must call setPreviewDisplay first
+// start preview mode
 status_t Camera::startPreview()
 {
     LOGV("startPreview");
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index fd3a4ba..e76967d 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -501,4 +501,6 @@
       "http://sridharg.googlejunta.com/yslau/stress_media/mp3_regular.mp3";
   public static final String STREAM_MPEG4_QVGA_128k = 
       "http://sridharg.googlejunta.com/yslau/stress_media/mpeg4_qvga_24fps.3gp";
+  public static final int STREAM_H264_480_360_1411k_DURATION = 46000;
+  public static final int VIDEO_H263_AAC_DURATION = 501000;
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
index 12eacd3..ae9e102 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaRecorderStressTestRunner.java
@@ -19,6 +19,7 @@
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
 import com.android.mediaframeworktest.stress.MediaRecorderStressTest;
+import com.android.mediaframeworktest.stress.MediaPlayerStressTest;
 
 import junit.framework.TestSuite;
 
@@ -28,6 +29,7 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(MediaRecorderStressTest.class);
+        suite.addTestSuite(MediaPlayerStressTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
new file mode 100644
index 0000000..5e213d7
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.stress;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+
+import android.hardware.Camera;
+import android.media.MediaPlayer;
+import android.media.MediaRecorder;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import com.android.mediaframeworktest.MediaNames;
+
+import java.util.Random;
+
+/**
+ * Junit / Instrumentation test case for the media player
+ */
+public class MediaPlayerStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {    
+    private String TAG = "MediaPlayerStressTest";
+    private MediaRecorder mRecorder;
+    private Camera mCamera;
+
+    private static final int NUMBER_OF_RANDOM_REPOSITION_AND_PLAY = 10;
+    private static final int NUMBER_OF_RANDOM_REPOSITION_AND_PLAY_SHORT = 5;
+    private static final int NUMBER_OF_STRESS_LOOPS = 1000;
+    private static final int PLAYBACK_END_TOLERANCE = 5000;
+    private static final int WAIT_UNTIL_PLAYBACK_FINISH = 515000 ;
+
+    public MediaPlayerStressTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        getActivity();
+        super.setUp();
+    }
+
+    @LargeTest
+    public void testStressHWDecoderRelease() throws Exception {
+        SurfaceHolder mSurfaceHolder;
+        long randomseed = System.currentTimeMillis(); 
+        Random generator = new Random(randomseed);
+        Log.v(TAG, "Random seed: " + randomseed);
+        int video_duration = MediaNames.STREAM_H264_480_360_1411k_DURATION;
+        int random_play_time;
+
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        try {
+            for (int i = 0; i < NUMBER_OF_STRESS_LOOPS; i++) {
+                MediaPlayer mp = new MediaPlayer();
+                mp.setDataSource(MediaNames.STREAM_H264_480_360_1411k);
+                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+                mp.prepare();
+                mp.start();
+                // seek and play
+                for (int j = 0; j < generator.nextInt(10); j++) {
+                    random_play_time =
+                        generator.nextInt(MediaNames.STREAM_H264_480_360_1411k_DURATION / 2);
+                    Log.v(TAG, "Play time = " + random_play_time);
+                    Thread.sleep(random_play_time);
+                    int seek_time = MediaNames.STREAM_H264_480_360_1411k_DURATION / 2;
+                    Log.v(TAG, "Seek time = " + seek_time);
+                    mp.seekTo(seek_time);
+                }
+                mp.release();
+            }
+
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+    }
+
+    @LargeTest
+    public void testStressGetCurrentPosition() throws Exception {
+        SurfaceHolder mSurfaceHolder;
+        long randomseed = System.currentTimeMillis(); 
+        Random generator = new Random(randomseed);
+        Log.v(TAG, "Random seed: " + randomseed);
+        int video_duration = MediaNames.VIDEO_H263_AAC_DURATION;
+        int random_play_time = 0;
+        int random_seek_time = 0;
+
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        try {
+            for (int i = 0; i < NUMBER_OF_STRESS_LOOPS; i++) {
+                MediaPlayer mp = new MediaPlayer();
+                mp.setDataSource(MediaNames.VIDEO_H263_AMR);
+                mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+                mp.prepare();
+                mp.start();
+                // Random seek and play
+                for (int j = 0; j < generator.nextInt(10); j++) {
+                    random_play_time =
+                        generator.nextInt(video_duration / 2);
+                    Log.v(TAG, "Play time = " + random_play_time);
+                    Thread.sleep(random_play_time);
+                    random_seek_time =
+                        generator.nextInt(video_duration / 2);
+                    Log.v(TAG, "Seek time = " + random_seek_time);
+                    mp.seekTo(random_seek_time);
+                }
+                //wait until the movie finish and check the current position
+                //Make sure the wait time is long enough
+                long wait_until_playback_finish = video_duration - random_seek_time + PLAYBACK_END_TOLERANCE * 2;
+                Thread.sleep(wait_until_playback_finish);
+                Log.v(TAG, "CurrentPosition = " + mp.getCurrentPosition());
+                if ( mp.isPlaying() || mp.getCurrentPosition() > (video_duration + PLAYBACK_END_TOLERANCE)){
+                    assertTrue("Current PlayTime greater than duration", false);
+                }
+                mp.release();
+            }
+
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+    }
+}
+
diff --git a/packages/TtsService/AndroidManifest.xml b/packages/TtsService/AndroidManifest.xml
index 1dc25c6..fab2534 100755
--- a/packages/TtsService/AndroidManifest.xml
+++ b/packages/TtsService/AndroidManifest.xml
@@ -12,4 +12,5 @@
         </service>
     </application>
     <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 </manifest>
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 69ba062..a55b704 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -199,6 +199,7 @@
         if (wav == NULL) {
             delete pForAfter;
             LOGV("Null: speech has completed");
+            return TTS_CALLBACK_HALT;
         }
         if (bufferSize > 0){
             fwrite(wav, 1, bufferSize, pForAfter->outputFile);
@@ -213,8 +214,12 @@
         // this struct was allocated in the original android_tts_SynthProxy_speak call,
         // all processing matching this call is now done.
         LOGV("Speech synthesis done.");
-        delete pForAfter;
-        pForAfter = NULL;
+        if (pForAfter->usageMode == USAGEMODE_PLAY_IMMEDIATELY) {
+            // only delete for direct playback. When writing to a file, we still have work to do
+            // in android_tts_SynthProxy_synthesizeToFile. The struct will be deleted there.
+            delete pForAfter;
+            pForAfter = NULL;
+        }
         return TTS_CALLBACK_HALT;
     }
 
@@ -397,7 +402,6 @@
 }
 
 
-// TODO: Refactor this to get rid of any assumptions about sample rate, etc.
 static void
 android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData,
         jstring textJavaString, jstring filenameJavaString)
@@ -408,6 +412,21 @@
     }
 
     SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
+    if (!pSynthData->mNativeSynthInterface) {
+        LOGE("android_tts_SynthProxy_synthesizeToFile(): invalid engine handle");
+        return;
+    }
+
+    // Retrieve audio parameters before writing the file header
+    AudioSystem::audio_format encoding = DEFAULT_TTS_FORMAT;
+    uint32_t rate = DEFAULT_TTS_RATE;
+    int channels = DEFAULT_TTS_NB_CHANNELS;
+    pSynthData->mNativeSynthInterface->setAudioFormat(encoding, rate, channels);
+
+    if ((encoding != AudioSystem::PCM_16_BIT) && (encoding != AudioSystem::PCM_8_BIT)) {
+        LOGE("android_tts_SynthProxy_synthesizeToFile(): engine uses invalid format");
+        return;
+    }
 
     const char *filenameNativeString =
             env->GetStringUTFChars(filenameJavaString, 0);
@@ -419,6 +438,12 @@
 
     pForAfter->outputFile = fopen(filenameNativeString, "wb");
 
+    if (pForAfter->outputFile == NULL) {
+        LOGE("android_tts_SynthProxy_synthesizeToFile(): error creating output file");
+        delete pForAfter;
+        return;
+    }
+
     // Write 44 blank bytes for WAV header, then come back and fill them in
     // after we've written the audio data
     char header[44];
@@ -427,10 +452,8 @@
     unsigned int unique_identifier;
 
     // TODO check return codes
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->synthesizeText(textNativeString, pSynthData->mBuffer, pSynthData->mBufferSize,
-                (void *)pForAfter);
-    }
+    pSynthData->mNativeSynthInterface->synthesizeText(textNativeString, pSynthData->mBuffer,
+            pSynthData->mBufferSize, (void *)pForAfter);
 
     long filelen = ftell(pForAfter->outputFile);
 
@@ -452,12 +475,14 @@
 
     ((uint32_t *)(&header[16]))[0] = 16;  // size of fmt
 
+    int sampleSizeInByte = (encoding == AudioSystem::PCM_16_BIT ? 2 : 1);
+
     ((unsigned short *)(&header[20]))[0] = 1;  // format
-    ((unsigned short *)(&header[22]))[0] = 1;  // channels
-    ((uint32_t *)(&header[24]))[0] = 22050;  // samplerate
-    ((uint32_t *)(&header[28]))[0] = 44100;  // byterate
-    ((unsigned short *)(&header[32]))[0] = 2;  // block align
-    ((unsigned short *)(&header[34]))[0] = 16;  // bits per sample
+    ((unsigned short *)(&header[22]))[0] = channels;  // channels
+    ((uint32_t *)(&header[24]))[0] = rate;  // samplerate
+    ((uint32_t *)(&header[28]))[0] = rate * sampleSizeInByte * channels;// byterate
+    ((unsigned short *)(&header[32]))[0] = sampleSizeInByte * channels;  // block align
+    ((unsigned short *)(&header[34]))[0] = sampleSizeInByte * 8;  // bits per sample
 
     header[36] = 'd';
     header[37] = 'a';
@@ -473,6 +498,9 @@
     fflush(pForAfter->outputFile);
     fclose(pForAfter->outputFile);
 
+    delete pForAfter;
+    pForAfter = NULL;
+
     env->ReleaseStringUTFChars(textJavaString, textNativeString);
     env->ReleaseStringUTFChars(filenameJavaString, filenameNativeString);
 }
@@ -500,8 +528,8 @@
 
     if (pSynthData->mNativeSynthInterface) {
         const char *textNativeString = env->GetStringUTFChars(textJavaString, 0);
-        pSynthData->mNativeSynthInterface->synthesizeText(textNativeString, pSynthData->mBuffer, pSynthData->mBufferSize,
-                (void *)pForAfter);
+        pSynthData->mNativeSynthInterface->synthesizeText(textNativeString, pSynthData->mBuffer,
+                pSynthData->mBufferSize, (void *)pForAfter);
         env->ReleaseStringUTFChars(textJavaString, textNativeString);
     }
 }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 4a2808b..854138c 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -25,15 +25,20 @@
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentQueryMap;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.media.AsyncPlayer;
 import android.media.AudioManager;
 import android.net.Uri;
@@ -88,6 +93,12 @@
     private NotificationRecord mVibrateNotification;
     private Vibrator mVibrator = new Vibrator();
 
+    // adb
+    private int mBatteryPlugged;
+    private boolean mAdbEnabled = false;
+    private boolean mAdbNotificationShown = false;
+    private Notification mAdbNotification;
+    
     private ArrayList<NotificationRecord> mNotificationList;
 
     private ArrayList<ToastRecord> mToastQueue;
@@ -297,6 +308,9 @@
                     mBatteryFull = batteryFull;
                     updateLights();
                 }
+                
+                mBatteryPlugged = intent.getIntExtra("plugged", 0);
+                updateAdbNotification();
             } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
                     || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
                 Uri uri = intent.getData();
@@ -312,6 +326,31 @@
         }
     };
 
+    class SettingsObserver extends ContentObserver {
+        SettingsObserver(Handler handler) {
+            super(handler);
+        }
+        
+        void observe() {
+            ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.ADB_ENABLED), false, this);
+            update();
+        }
+
+        @Override public void onChange(boolean selfChange) {
+            update();
+        }
+
+        public void update() {
+            ContentResolver resolver = mContext.getContentResolver();
+            mAdbEnabled = Settings.Secure.getInt(resolver,
+                        Settings.Secure.ADB_ENABLED, 0) != 0;
+            updateAdbNotification();
+        }
+    }
+    private final SettingsObserver mSettingsObserver;
+    
     NotificationManagerService(Context context, StatusBarService statusBar,
             HardwareService hardware)
     {
@@ -333,6 +372,9 @@
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
         mContext.registerReceiver(mIntentReceiver, filter);
+        
+        mSettingsObserver = new SettingsObserver(mHandler);
+        mSettingsObserver.observe();
     }
 
     // Toasts
@@ -892,6 +934,62 @@
         return -1;
     }
 
+    // This is here instead of StatusBarPolicy because it is an important
+    // security feature that we don't want people customizing the platform
+    // to accidentally lose.
+    private void updateAdbNotification() {
+        if (mAdbEnabled && mBatteryPlugged == BatteryManager.BATTERY_PLUGGED_USB) {
+            if (!mAdbNotificationShown) {
+                NotificationManager notificationManager = (NotificationManager) mContext
+                        .getSystemService(Context.NOTIFICATION_SERVICE);
+                if (notificationManager != null) {
+                    Resources r = mContext.getResources();
+                    CharSequence title = r.getText(
+                            com.android.internal.R.string.adb_active_notification_title);
+                    CharSequence message = r.getText(
+                            com.android.internal.R.string.adb_active_notification_message);
+
+                    if (mAdbNotification == null) {
+                        mAdbNotification = new Notification();
+                        mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_warning;
+                        mAdbNotification.when = 0;
+                        mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT;
+                        mAdbNotification.tickerText = title;
+                        mAdbNotification.defaults |= Notification.DEFAULT_SOUND;
+                    }
+
+                    Intent intent = new Intent(
+                            Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                    // Note: we are hard-coding the component because this is
+                    // an important security UI that we don't want anyone
+                    // intercepting.
+                    intent.setComponent(new ComponentName("com.android.settings",
+                            "com.android.settings.DevelopmentSettings"));
+                    PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+                            intent, 0);
+
+                    mAdbNotification.setLatestEventInfo(mContext, title, message, pi);
+                    
+                    mAdbNotificationShown = true;
+                    notificationManager.notify(
+                            com.android.internal.R.string.adb_active_notification_title,
+                            mAdbNotification);
+                }
+            }
+            
+        } else if (mAdbNotificationShown) {
+            NotificationManager notificationManager = (NotificationManager) mContext
+                    .getSystemService(Context.NOTIFICATION_SERVICE);
+            if (notificationManager != null) {
+                mAdbNotificationShown = false;
+                notificationManager.cancel(
+                        com.android.internal.R.string.adb_active_notification_title);
+            }
+        }
+    }
+    
     // ======================================================================
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/java/com/android/server/PackageManagerBackupAgent.java
index 16f14e8..a1b4c268 100644
--- a/services/java/com/android/server/PackageManagerBackupAgent.java
+++ b/services/java/com/android/server/PackageManagerBackupAgent.java
@@ -59,7 +59,14 @@
 
     private List<PackageInfo> mAllPackages;
     private PackageManager mPackageManager;
+    // version & signature info of each app in a restore set
     private HashMap<String, Metadata> mRestoredSignatures;
+    // The version info of each backed-up app as read from the state file
+    private HashMap<String, Metadata> mStateVersions = new HashMap<String, Metadata>();
+
+    private final HashSet<String> mExisting = new HashSet<String>();
+    private int mStoredSdkVersion;
+    private String mStoredIncrementalVersion;
 
     public class Metadata {
         public int versionCode;
@@ -96,24 +103,39 @@
 
         ByteArrayOutputStream bufStream = new ByteArrayOutputStream();  // we'll reuse these
         DataOutputStream outWriter = new DataOutputStream(bufStream);
-        HashSet<String> existing = parseStateFile(oldState);
+        parseStateFile(oldState);
+
+        // If the stored version string differs, we need to re-backup all
+        // of the metadata.  We force this by removing everything from the
+        // "already backed up" map built by parseStateFile().
+        if (mStoredIncrementalVersion == null
+                || !mStoredIncrementalVersion.equals(Build.VERSION.INCREMENTAL)) {
+            Log.i(TAG, "Previous metadata " + mStoredIncrementalVersion + " mismatch vs "
+                    + Build.VERSION.INCREMENTAL + " - rewriting");
+            mExisting.clear();
+        }
 
         try {
             /*
              * Global metadata:
              *
-             * int version -- the SDK version of the OS itself on the device
-             *                that produced this backup set.  Used to reject
-             *                backups from later OSes onto earlier ones.
+             * int SDKversion -- the SDK version of the OS itself on the device
+             *                   that produced this backup set.  Used to reject
+             *                   backups from later OSes onto earlier ones.
+             * String incremental -- the incremental release name of the OS stored in
+             *                       the backup set.
              */
-            if (!existing.contains(GLOBAL_METADATA_KEY)) {
+            if (!mExisting.contains(GLOBAL_METADATA_KEY)) {
                 if (DEBUG) Log.v(TAG, "Storing global metadata key");
                 outWriter.writeInt(Build.VERSION.SDK_INT);
+                outWriter.writeUTF(Build.VERSION.INCREMENTAL);
                 byte[] metadata = bufStream.toByteArray();
                 data.writeEntityHeader(GLOBAL_METADATA_KEY, metadata.length);
                 data.writeEntityData(metadata, metadata.length);
             } else {
                 if (DEBUG) Log.v(TAG, "Global metadata key already stored");
+                // don't consider it to have been skipped/deleted
+                mExisting.remove(GLOBAL_METADATA_KEY);
             }
 
             // For each app we have on device, see if we've backed it up yet.  If not,
@@ -123,11 +145,36 @@
                 if (packName.equals(GLOBAL_METADATA_KEY)) {
                     // We've already handled the metadata key; skip it here
                     continue;
-                } else if (!existing.contains(packName)) {
-                    // We haven't stored this app's signatures yet, so we do that now
+                } else {
+                    PackageInfo info = null;
                     try {
-                        PackageInfo info = mPackageManager.getPackageInfo(packName,
+                        info = mPackageManager.getPackageInfo(packName,
                                 PackageManager.GET_SIGNATURES);
+                    } catch (NameNotFoundException e) {
+                        // Weird; we just found it, and now are told it doesn't exist.
+                        // Treat it as having been removed from the device.
+                        mExisting.add(packName);
+                        continue;
+                    }
+
+                    boolean doBackup = false;
+                    if (!mExisting.contains(packName)) {
+                        // We haven't backed up this app before
+                        doBackup = true;
+                    } else {
+                        // We *have* backed this one up before.  Check whether the version
+                        // of the backup matches the version of the current app; if they
+                        // don't match, the app has been updated and we need to store its
+                        // metadata again.  In either case, take it out of mExisting so that
+                        // we don't consider it deleted later.
+                        if (info.versionCode != mStateVersions.get(packName).versionCode) {
+                            doBackup = true;
+                        }
+                        mExisting.remove(packName);
+                    }
+
+                    if (doBackup) {
+                        // We need to store this app's metadata
                         /*
                          * Metadata for each package:
                          *
@@ -135,7 +182,7 @@
                          * byte[] signatures -- [len] flattened Signature[] of the package
                          */
 
-                        // marshall the version code in a canonical form
+                        // marshal the version code in a canonical form
                         bufStream.reset();
                         outWriter.writeInt(info.versionCode);
                         byte[] versionBuf = bufStream.toByteArray();
@@ -153,18 +200,6 @@
                         data.writeEntityHeader(packName, versionBuf.length + sigs.length);
                         data.writeEntityData(versionBuf, versionBuf.length);
                         data.writeEntityData(sigs, sigs.length);
-                    } catch (NameNotFoundException e) {
-                        // Weird; we just found it, and now are told it doesn't exist.
-                        // Treat it as having been removed from the device.
-                        existing.add(packName);
-                    }
-                } else {
-                    // We've already backed up this app.  Remove it from the set so
-                    // we can tell at the end what has disappeared from the device.
-                    // !!! TODO: take out the debugging message
-                    if (DEBUG) Log.v(TAG, "= already backed up metadata for " + packName);
-                    if (!existing.remove(packName)) {
-                        Log.d(TAG, "*** failed to remove " + packName + " from package set!");
                     }
                 }
             }
@@ -172,7 +207,7 @@
             // At this point, the only entries in 'existing' are apps that were
             // mentioned in the saved state file, but appear to no longer be present
             // on the device.  Write a deletion entity for them.
-            for (String app : existing) {
+            for (String app : mExisting) {
                 // !!! TODO: take out this msg
                 if (DEBUG) Log.v(TAG, "- removing metadata for deleted pkg " + app);
                 try {
@@ -215,17 +250,21 @@
             DataInputStream in = new DataInputStream(baStream);
 
             if (key.equals(GLOBAL_METADATA_KEY)) {
-                storedSystemVersion = in.readInt();
+                int storedSdkVersion = in.readInt();
                 if (DEBUG) Log.v(TAG, "   storedSystemVersion = " + storedSystemVersion);
                 if (storedSystemVersion > Build.VERSION.SDK_INT) {
                     // returning before setting the sig map means we rejected the restore set
                     Log.w(TAG, "Restore set was from a later version of Android; not restoring");
                     return;
                 }
+                mStoredSdkVersion = storedSdkVersion;
+                mStoredIncrementalVersion = in.readUTF();
                 // !!! TODO: remove this debugging output
                 if (DEBUG) {
                     Log.i(TAG, "Restore set version " + storedSystemVersion
-                            + " is compatible with OS version " + Build.VERSION.SDK_INT);
+                            + " is compatible with OS version " + Build.VERSION.SDK_INT
+                            + " (" + mStoredIncrementalVersion + " vs "
+                            + Build.VERSION.INCREMENTAL + ")");
                 }
             } else {
                 // it's a file metadata record
@@ -302,31 +341,45 @@
     }
 
     // Util: parse out an existing state file into a usable structure
-    private HashSet<String> parseStateFile(ParcelFileDescriptor stateFile) {
-        HashSet<String> set = new HashSet<String>();
+    private void parseStateFile(ParcelFileDescriptor stateFile) {
+        mExisting.clear();
+        mStateVersions.clear();
+        mStoredSdkVersion = 0;
+        mStoredIncrementalVersion = null;
+
         // The state file is just the list of app names we have stored signatures for
+        // with the exception of the metadata block, to which is also appended the
+        // version numbers corresponding with the last time we wrote this PM block.
+        // If they mismatch the current system, we'll re-store the metadata key.
         FileInputStream instream = new FileInputStream(stateFile.getFileDescriptor());
         DataInputStream in = new DataInputStream(instream);
 
         int bufSize = 256;
         byte[] buf = new byte[bufSize];
         try {
-            int nameSize = in.readInt();
-            if (bufSize < nameSize) {
-                bufSize = nameSize + 32;
-                buf = new byte[bufSize];
+            String pkg = in.readUTF();
+            if (pkg.equals(GLOBAL_METADATA_KEY)) {
+                mStoredSdkVersion = in.readInt();
+                mStoredIncrementalVersion = in.readUTF();
+                mExisting.add(GLOBAL_METADATA_KEY);
+            } else {
+                Log.e(TAG, "No global metadata in state file!");
+                return;
             }
-            in.read(buf, 0, nameSize);
-            String pkg = new String(buf, 0, nameSize);
-            set.add(pkg);
+
+            // The global metadata was first; now read all the apps
+            while (true) {
+                pkg = in.readUTF();
+                int versionCode = in.readInt();
+                mExisting.add(pkg);
+                mStateVersions.put(pkg, new Metadata(versionCode, null));
+            }
         } catch (EOFException eof) {
             // safe; we're done
         } catch (IOException e) {
             // whoops, bad state file.  abort.
-            Log.e(TAG, "Unable to read Package Manager state file");
-            return null;
+            Log.e(TAG, "Unable to read Package Manager state file: " + e);
         }
-        return set;
     }
 
     // Util: write out our new backup state file
@@ -336,15 +389,14 @@
 
         try {
             // by the time we get here we know we've stored the global metadata record
-            byte[] metaNameBuf = GLOBAL_METADATA_KEY.getBytes();
-            out.writeInt(metaNameBuf.length);
-            out.write(metaNameBuf);
+            out.writeUTF(GLOBAL_METADATA_KEY);
+            out.writeInt(Build.VERSION.SDK_INT);
+            out.writeUTF(Build.VERSION.INCREMENTAL);
 
             // now write all the app names too
             for (PackageInfo pkg : pkgs) {
-                byte[] pkgNameBuf = pkg.packageName.getBytes();
-                out.writeInt(pkgNameBuf.length);
-                out.write(pkgNameBuf);
+                out.writeUTF(pkg.packageName);
+                out.writeInt(pkg.versionCode);
             }
         } catch (IOException e) {
             Log.e(TAG, "Unable to write package manager state file!");
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index dd3d38c..7a8d4e5e 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -99,7 +99,7 @@
     private IBinder mBatteryIcon;
     private IconData mBatteryData;
     private boolean mBatteryFirst = true;
-    private boolean mBatteryPlugged;
+    private int mBatteryPlugged;
     private int mBatteryLevel;
     private int mBatteryThreshold = 0; // index into mBatteryThresholds
     private int[] mBatteryThresholds = new int[] { 20, 15, -1 };
@@ -108,6 +108,7 @@
     private View mBatteryView;
     private int mBatteryViewSequence;
     private boolean mBatteryShowLowOnEndCall = false;
+    private boolean mSentLowBatteryBroadcast = false;
     private static final boolean SHOW_LOW_BATTERY_WARNING = true;
 
     // phone
@@ -581,7 +582,7 @@
         mBatteryData.iconLevel = intent.getIntExtra("level", 0);
         mService.updateIcon(mBatteryIcon, mBatteryData, null);
 
-        boolean plugged = intent.getIntExtra("plugged", 0) != 0;
+        int plugged = intent.getIntExtra("plugged", 0);
         int level = intent.getIntExtra("level", -1);
         if (false) {
             Log.d(TAG, "updateBattery level=" + level
@@ -592,7 +593,7 @@
                     + " mBatteryFirst=" + mBatteryFirst);
         }
 
-        boolean oldPlugged = mBatteryPlugged;
+        int oldPlugged = mBatteryPlugged;
         int oldThreshold = mBatteryThreshold;
         pickNextBatteryLevel(level);
 
@@ -619,11 +620,12 @@
             Log.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level
                     + " mBatteryThreshold=" + mBatteryThreshold + " oldThreshold=" + oldThreshold);
         }
-        if (!plugged
-                && ((oldPlugged && level < mBatteryThresholds[BATTERY_THRESHOLD_WARNING])
+        if (plugged == 0
+                && ((oldPlugged != 0 && level < mBatteryThresholds[BATTERY_THRESHOLD_WARNING])
                     || (mBatteryThreshold > oldThreshold
                         && mBatteryThreshold > BATTERY_THRESHOLD_WARNING))) {
             // Broadcast the low battery warning
+            mSentLowBatteryBroadcast = true;
             mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_LOW));
 
             if (SHOW_LOW_BATTERY_WARNING) {
@@ -639,7 +641,11 @@
                     mBatteryShowLowOnEndCall = true;
                 }
             }
-        } else if (mBatteryThreshold == BATTERY_THRESHOLD_CLOSE_WARNING) {
+        } else if (mBatteryThreshold < BATTERY_THRESHOLD_WARNING) {
+            if (mSentLowBatteryBroadcast == true) {
+                mSentLowBatteryBroadcast = false;
+                mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_OKAY));
+            }
             if (SHOW_LOW_BATTERY_WARNING) {
                 if (mLowBatteryDialog != null) {
                     mLowBatteryDialog.dismiss();
@@ -763,7 +769,7 @@
         }
         if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
             if (mBatteryShowLowOnEndCall) {
-                if (!mBatteryPlugged) {
+                if (mBatteryPlugged == 0) {
                     showLowBatteryWarning();
                 }
                 mBatteryShowLowOnEndCall = false;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index e00ee83..c33d4b6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -1398,7 +1398,7 @@
 
     protected void onVoiceCallEnded() {
         if (state == State.CONNECTED) {
-            if (mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+            if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) {
                 startNetStatPoll();
                 phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
             } else {
diff --git a/test-runner/android/test/MoreAsserts.java b/test-runner/android/test/MoreAsserts.java
index 2e74644..9e0d018 100644
--- a/test-runner/android/test/MoreAsserts.java
+++ b/test-runner/android/test/MoreAsserts.java
@@ -24,6 +24,7 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.ArrayList;
 import java.util.regex.MatchResult;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -316,8 +317,11 @@
      */
     public static void assertContentsInOrder(
             String message, Iterable<?> actual, Object... expected) {
-        Assert.assertEquals(message,
-                Arrays.asList(expected), Lists.newArrayList(actual));
+        ArrayList actualList = new ArrayList();
+        for (Object o : actual) {
+            actualList.add(o);
+        }
+        Assert.assertEquals(message, Arrays.asList(expected), actualList);
     }
 
     /**
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index c792e8e..cbcac6c 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -16,18 +16,15 @@
 
 package com.android.dumprendertree;
 
+import dalvik.system.VMRuntime;
+
 import android.app.Instrumentation;
 import android.content.Intent;
-
-import android.util.Log;
-
 import android.os.Bundle;
 import android.os.Debug;
-import android.os.Debug.MemoryInfo;
+import android.os.Process;
 import android.test.ActivityInstrumentationTestCase2;
-
-import com.android.dumprendertree.TestShellActivity;
-import com.android.dumprendertree.TestShellCallback;
+import android.util.Log;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -70,9 +67,7 @@
         TestShellActivity activity = (TestShellActivity) getActivity();
 
         Log.v(LOGTAG, "About to run tests, calling gc first...");
-        Runtime.getRuntime().runFinalization();
-        Runtime.getRuntime().gc();
-        Runtime.getRuntime().gc();
+        freeMem();
 
         // Run tests
         runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis);
@@ -83,46 +78,73 @@
         activity.finish();
     }
 
+    private void freeMem() {
+        Log.v(LOGTAG, "freeMem: calling gc/finalization...");
+        final VMRuntime runtime = VMRuntime.getRuntime();
+
+        runtime.gcSoftReferences();
+        runtime.runFinalizationSync();
+        runtime.gcSoftReferences();
+        runtime.runFinalizationSync();
+        runtime.gcSoftReferences();
+        runtime.runFinalizationSync();
+        Runtime.getRuntime().runFinalization();
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().gc();
+
+    }
+
+    private void printRow(PrintStream ps, String format, Object...objs) {
+        ps.println(String.format(format, objs));
+    }
+
     private void dumpMemoryInfo() {
         try {
-            Log.v(LOGTAG, "About to dump meminfo, calling gc first...");
-            Runtime.getRuntime().runFinalization();
-            Runtime.getRuntime().gc();
-            Runtime.getRuntime().gc();
-
+            freeMem();
             Log.v(LOGTAG, "Dumping memory information.");
 
             FileOutputStream out = new FileOutputStream(LOAD_TEST_RESULT, true);
             PrintStream ps = new PrintStream(out);
 
-            MemoryInfo mi = new MemoryInfo();
-            Debug.getMemoryInfo(mi);
-
-            //try to fake the dumpsys format
-            //this will eventually be changed to XML
-            String format = "%15s:%9d%9d%9d%9d";
-            String pss =
-              String.format(format, "(Pss)",
-                  mi.nativePss, mi.dalvikPss, mi.otherPss,
-                  mi.nativePss + mi.dalvikPss + mi.otherPss);
-            String sd =
-              String.format(format, "(shared dirty)",
-                  mi.nativeSharedDirty, mi.dalvikSharedDirty, mi.otherSharedDirty,
-                  mi.nativeSharedDirty + mi.dalvikSharedDirty + mi.otherSharedDirty);
-            String pd =
-              String.format(format, "(priv dirty)",
-                  mi.nativePrivateDirty, mi.dalvikPrivateDirty, mi.otherPrivateDirty,
-                  mi.nativePrivateDirty + mi.dalvikPrivateDirty + mi.otherPrivateDirty);
-
             ps.print("\n\n\n");
-            ps.println("** MEMINFO in pid 0 [com.android.dumprendertree] **");
-            ps.println("                   native   dalvik    other    total");
-            ps.println("           size:    12060     5255      N/A    17315");
-            ps.println("      allocated:    12060     5255      N/A    17315");
-            ps.println("           free:    12060     5255      N/A    17315");
-            ps.println(pss);
-            ps.println(sd);
-            ps.println(pd);
+            ps.println("** MEMINFO in pid " + Process.myPid()
+                    + " [com.android.dumprendertree] **");
+            String formatString = "%17s %8s %8s %8s %8s";
+
+            long nativeMax = Debug.getNativeHeapSize() / 1024;
+            long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
+            long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
+            Runtime runtime = Runtime.getRuntime();
+            long dalvikMax = runtime.totalMemory() / 1024;
+            long dalvikFree = runtime.freeMemory() / 1024;
+            long dalvikAllocated = dalvikMax - dalvikFree;
+
+
+            Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
+            Debug.getMemoryInfo(memInfo);
+
+            final int nativeShared = memInfo.nativeSharedDirty;
+            final int dalvikShared = memInfo.dalvikSharedDirty;
+            final int otherShared = memInfo.otherSharedDirty;
+
+            final int nativePrivate = memInfo.nativePrivateDirty;
+            final int dalvikPrivate = memInfo.dalvikPrivateDirty;
+            final int otherPrivate = memInfo.otherPrivateDirty;
+
+            printRow(ps, formatString, "", "native", "dalvik", "other", "total");
+            printRow(ps, formatString, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
+            printRow(ps, formatString, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
+                    nativeAllocated + dalvikAllocated);
+            printRow(ps, formatString, "free:", nativeFree, dalvikFree, "N/A",
+                    nativeFree + dalvikFree);
+
+            printRow(ps, formatString, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
+                    memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
+
+            printRow(ps, formatString, "(shared dirty):", nativeShared, dalvikShared, otherShared,
+                    nativeShared + dalvikShared + otherShared);
+            printRow(ps, formatString, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
+                    nativePrivate + dalvikPrivate + otherPrivate);
             ps.print("\n\n\n");
             ps.flush();
             ps.close();
@@ -142,7 +164,7 @@
                     LoadTestsAutoTest.this.notifyAll();
                 }
             }
-            
+
             public void timedOut(String url) {
             }
         });