Merge "Remove RefBase.h dependency on TextOutput.h"
diff --git a/api/current.xml b/api/current.xml
index c4fc0e4..a36f066 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -35340,6 +35340,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_NEW_SEARCH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;new_search&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_SELECT_QUERY"
  type="java.lang.String"
  transient="false"
@@ -156122,6 +156133,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_CREATE_NEW_TAB"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;create_new_tab&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_HEADERS"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/animation/package.html b/core/java/android/animation/package.html
index ff43260..92eeb20 100644
--- a/core/java/android/animation/package.html
+++ b/core/java/android/animation/package.html
@@ -15,7 +15,7 @@
 
 <p>
 For a guide on how to use the property animation system, see the
-<a href="{@docRoot}guide/topics/media/index.html">Animation</a> developer guide.
+<a href="{@docRoot}guide/topics/graphics/animation.html">Animation</a> developer guide.
 </p>
 </body>
 </html>
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a660076..77dc084 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -30,11 +30,17 @@
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
+import android.util.Log;
+import com.android.internal.app.IUsageStats;
+import com.android.internal.os.PkgUsageStats;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Interact with the overall activities running in the system.
@@ -1233,4 +1239,29 @@
     public static boolean isRunningInTestHarness() {
         return SystemProperties.getBoolean("ro.test_harness", false);
     }
+
+    /**
+     * Returns the launch count of each installed package.
+     *
+     * @hide
+     */
+    public Map<String, Integer> getAllPackageLaunchCounts() {
+        try {
+            IUsageStats usageStatsService = IUsageStats.Stub.asInterface(
+                    ServiceManager.getService("usagestats"));
+            if (usageStatsService == null) {
+                return new HashMap<String, Integer>();
+            }
+
+            Map<String, Integer> launchCounts = new HashMap<String, Integer>();
+            for (PkgUsageStats pkgUsageStats : usageStatsService.getAllPkgUsageStats()) {
+                launchCounts.put(pkgUsageStats.packageName, pkgUsageStats.launchCount);
+            }
+
+            return launchCounts;
+        } catch (RemoteException e) {
+            Log.w(TAG, "Could not query launch counts", e);
+            return new HashMap<String, Integer>();
+        }
+    }
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4370ebf..ccd65de 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -82,6 +82,7 @@
 
     /**
      * The resource id of a drawable to use as the icon in the status bar.
+     * This is required; notifications with an invalid icon resource will not be shown.
      */
     public int icon;
 
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index e3242c1..6541c54 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -83,12 +83,14 @@
     }
 
     /**
-     * Persistent notification on the status bar, 
+     * Post a notification to be shown in the status bar. If a notification with
+     * the same id has already been posted by your application and has not yet been canceled, it
+     * will be replaced by the updated information.
      *
      * @param id An identifier for this notification unique within your
      *        application.
-     * @param notification A {@link Notification} object describing how to
-     *        notify the user, other than the view you're providing. Must not be null.
+     * @param notification A {@link Notification} object describing what to show the user. Must not
+     *        be null.
      */
     public void notify(int id, Notification notification)
     {
@@ -96,13 +98,15 @@
     }
 
     /**
-     * Persistent notification on the status bar,
+     * Post a notification to be shown in the status bar. If a notification with
+     * the same tag and id has already been posted by your application and has not yet been
+     * canceled, it will be replaced by the updated information.
      *
      * @param tag A string identifier for this notification.  May be {@code null}.
      * @param id An identifier for this notification.  The pair (tag, id) must be unique
      *        within your application.
-     * @param notification A {@link Notification} object describing how to
-     *        notify the user, other than the view you're providing. Must not be null.
+     * @param notification A {@link Notification} object describing what to
+     *        show the user. Must not be null.
      */
     public void notify(String tag, int id, Notification notification)
     {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 6715012..aab087f 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -138,6 +138,12 @@
     public final static String EXTRA_SELECT_QUERY = "select_query";
 
     /**
+     * Boolean extra data key for {@link Intent#ACTION_WEB_SEARCH} intents.  If {@code true},
+     * this search should open a new browser window, rather than using an existing one.
+     */
+    public final static String EXTRA_NEW_SEARCH = "new_search";
+
+    /**
      * Boolean extra data key for a suggestion provider to return in {@link Cursor#getExtras} to
      * indicate that the search is not complete yet. This can be used by the search UI
      * to indicate that a search is in progress. The suggestion provider can return partial results
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index c2f3ae7..d8a5b45 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -508,23 +508,86 @@
      * finish processing the data in them.
      *
      * <p>The size of the buffer is determined by multiplying the preview
-     * image width, height, and bytes per pixel.  The width and height can be
-     * read from {@link Camera.Parameters#getPreviewSize()}.  Bytes per pixel
+     * image width, height, and bytes per pixel. The width and height can be
+     * read from {@link Camera.Parameters#getPreviewSize()}. Bytes per pixel
      * can be computed from
      * {@link android.graphics.ImageFormat#getBitsPerPixel(int)} / 8,
      * using the image format from {@link Camera.Parameters#getPreviewFormat()}.
      *
      * <p>This method is only necessary when
-     * {@link #setPreviewCallbackWithBuffer(PreviewCallback)} is used.  When
+     * {@link #setPreviewCallbackWithBuffer(PreviewCallback)} is used. When
      * {@link #setPreviewCallback(PreviewCallback)} or
      * {@link #setOneShotPreviewCallback(PreviewCallback)} are used, buffers
-     * are automatically allocated.
+     * are automatically allocated. When a supplied buffer is too small to
+     * hold the preview frame data, preview callback will return null and
+     * the buffer will be removed from the buffer queue.
      *
      * @param callbackBuffer the buffer to add to the queue.
      *     The size should be width * height * bits_per_pixel / 8.
      * @see #setPreviewCallbackWithBuffer(PreviewCallback)
      */
-    public native final void addCallbackBuffer(byte[] callbackBuffer);
+    public final void addCallbackBuffer(byte[] callbackBuffer)
+    {
+        _addCallbackBuffer(callbackBuffer, CAMERA_MSG_PREVIEW_FRAME);
+    }
+
+    /**
+     * Adds a pre-allocated buffer to the raw image callback buffer queue.
+     * Applications can add one or more buffers to the queue. When a raw image
+     * frame arrives and there is still at least one available buffer, the
+     * buffer will be used to hold the raw image data and removed from the
+     * queue. Then raw image callback is invoked with the buffer. If a raw
+     * image frame arrives but there is no buffer left, the frame is
+     * discarded. Applications should add buffers back when they finish
+     * processing the data in them by calling this method again in order
+     * to avoid running out of raw image callback buffers.
+     *
+     * <p>The size of the buffer is determined by multiplying the raw image
+     * width, height, and bytes per pixel. The width and height can be
+     * read from {@link Camera.Parameters#getPictureSize()}. Bytes per pixel
+     * can be computed from
+     * {@link android.graphics.ImageFormat#getBitsPerPixel(int)} / 8,
+     * using the image format from {@link Camera.Parameters#getPreviewFormat()}.
+     *
+     * <p>This method is only necessary when the PictureCallbck for raw image
+     * is used while calling {@link #takePicture(Camera.ShutterCallback,
+     * Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)}.
+     *
+     * Please note that by calling this method, the mode for application-managed
+     * callback buffers is triggered. If this method has never been called,
+     * null will be returned by the raw image callback since there is
+     * no image callback buffer available. Furthermore, When a supplied buffer
+     * is too small to hold the raw image data, raw image callback will return
+     * null and the buffer will be removed from the buffer queue.
+     *
+     * @param callbackBuffer the buffer to add to the raw image callback buffer
+     *     queue. The size should be width * height * (bits per pixel) / 8. An
+     *     null callbackBuffer will be ignored and won't be added to the queue.
+     *
+     * @see #takePicture(Camera.ShutterCallback,
+     * Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)}.
+     *
+     * {@hide}
+     */
+    public final void addRawImageCallbackBuffer(byte[] callbackBuffer)
+    {
+        addCallbackBuffer(callbackBuffer, CAMERA_MSG_RAW_IMAGE);
+    }
+
+    private final void addCallbackBuffer(byte[] callbackBuffer, int msgType)
+    {
+        // CAMERA_MSG_VIDEO_FRAME may be allowed in the future.
+        if (msgType != CAMERA_MSG_PREVIEW_FRAME &&
+            msgType != CAMERA_MSG_RAW_IMAGE) {
+            throw new IllegalArgumentException(
+                            "Unsupported message type: " + msgType);
+        }
+
+        _addCallbackBuffer(callbackBuffer, msgType);
+    }
+
+    private native final void _addCallbackBuffer(
+                                byte[] callbackBuffer, int msgType);
 
     private class EventHandler extends Handler
     {
@@ -735,7 +798,7 @@
             PictureCallback jpeg) {
         takePicture(shutter, raw, null, jpeg);
     }
-    private native final void native_takePicture();
+    private native final void native_takePicture(int msgType);
 
     /**
      * Triggers an asynchronous image capture. The camera service will initiate
@@ -743,7 +806,8 @@
      * The shutter callback occurs after the image is captured. This can be used
      * to trigger a sound to let the user know that image has been captured. The
      * raw callback occurs when the raw image data is available (NOTE: the data
-     * may be null if the hardware does not have enough memory to make a copy).
+     * will be null if there is no raw image callback buffer available or the
+     * raw image callback buffer is not large enough to hold the raw image).
      * The postview callback occurs when a scaled, fully processed postview
      * image is available (NOTE: not all hardware supports this). The jpeg
      * callback occurs when the compressed image is available. If the
@@ -762,6 +826,8 @@
      * @param raw       the callback for raw (uncompressed) image data, or null
      * @param postview  callback with postview image data, may be null
      * @param jpeg      the callback for JPEG image data, or null
+     *
+     * @see #addRawImageCallbackBuffer(byte[])
      */
     public final void takePicture(ShutterCallback shutter, PictureCallback raw,
             PictureCallback postview, PictureCallback jpeg) {
@@ -769,7 +835,23 @@
         mRawImageCallback = raw;
         mPostviewCallback = postview;
         mJpegCallback = jpeg;
-        native_takePicture();
+
+        // If callback is not set, do not send me callbacks.
+        int msgType = 0;
+        if (mShutterCallback != null) {
+            msgType |= CAMERA_MSG_SHUTTER;
+        }
+        if (mRawImageCallback != null) {
+            msgType |= CAMERA_MSG_RAW_IMAGE;
+        }
+        if (mPostviewCallback != null) {
+            msgType |= CAMERA_MSG_POSTVIEW_FRAME;
+        }
+        if (mJpegCallback != null) {
+            msgType |= CAMERA_MSG_COMPRESSED_IMAGE;
+        }
+
+        native_takePicture(msgType);
     }
 
     /**
diff --git a/core/java/android/pim/ICalendar.java b/core/java/android/pim/ICalendar.java
index cc0f45e..9c4eaf4 100644
--- a/core/java/android/pim/ICalendar.java
+++ b/core/java/android/pim/ICalendar.java
@@ -578,6 +578,23 @@
                             + text);
                 }
                 parameter.name = text.substring(startIndex + 1, equalIndex);
+            } else if (c == '"') {
+                if (parameter == null) {
+                    throw new FormatException("Expected parameter before '\"' in " + text);
+                }
+                if (equalIndex == -1) {
+                    throw new FormatException("Expected '=' within parameter in " + text);
+                }
+                if (state.index > equalIndex + 1) {
+                    throw new FormatException("Parameter value cannot contain a '\"' in " + text);
+                }
+                final int endQuote = text.indexOf('"', state.index + 1);
+                if (endQuote < 0) {
+                    throw new FormatException("Expected closing '\"' in " + text);
+                }
+                parameter.value = text.substring(state.index + 1, endQuote);
+                state.index = endQuote + 1;
+                return parameter;
             }
             ++state.index;
         }
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 3bfd005..57ee440 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -139,8 +139,6 @@
     public static final int SEARCHES_PROJECTION_SEARCH_INDEX = 1;
     public static final int SEARCHES_PROJECTION_DATE_INDEX = 2;
 
-    private static final String SEARCHES_WHERE_CLAUSE = "search = ?";
-
     /* Set a cap on the count of history items in the history/bookmark
        table, to prevent db and layout operations from dragging to a
        crawl.  Revisit this cap when/if db/layout performance
@@ -167,6 +165,13 @@
     }
 
     /**
+     * Passed along with an Intent to a browser, specifying that a new tab
+     * be created.  Overrides EXTRA_APPLICATION_ID; if both are set, a new tab
+     * will be used, rather than using the same one.
+     */
+    public static final String EXTRA_CREATE_NEW_TAB = "create_new_tab";
+
+    /**
      * Stores a Bitmap extra in an {@link Intent} representing the screenshot of
      * a page to share.  When receiving an {@link Intent#ACTION_SEND} from the
      * Browser, use this to access the screenshot.
diff --git a/core/java/android/webkit/SelectActionModeCallback.java b/core/java/android/webkit/SelectActionModeCallback.java
index ea09fc0..104deb1 100644
--- a/core/java/android/webkit/SelectActionModeCallback.java
+++ b/core/java/android/webkit/SelectActionModeCallback.java
@@ -83,6 +83,7 @@
             case com.android.internal.R.id.websearch:
                 mode.finish();
                 Intent i = new Intent(Intent.ACTION_WEB_SEARCH);
+                i.putExtra(SearchManager.EXTRA_NEW_SEARCH, true);
                 i.putExtra(SearchManager.QUERY, mWebView.getSelection());
                 mWebView.getContext().startActivity(i);
                 break;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index ef4e4e0..cf72ec4 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -701,8 +701,8 @@
 
             if (mProgress > max) {
                 mProgress = max;
-                refreshProgress(R.id.progress, mProgress, false);
             }
+            refreshProgress(R.id.progress, mProgress, false);
         }
     }
     
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 9f70509..bfbfd37 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -53,25 +53,48 @@
     virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
     virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);
     virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
-    void addCallbackBuffer(JNIEnv *env, jbyteArray cbb);
+    void addCallbackBuffer(JNIEnv *env, jbyteArray cbb, int msgType);
     void setCallbackMode(JNIEnv *env, bool installed, bool manualMode);
     sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
+    bool isRawImageCallbackBufferAvailable() const;
     void release();
 
 private:
     void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType);
+    void clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers);
     void clearCallbackBuffers_l(JNIEnv *env);
+    jbyteArray getCallbackBuffer(JNIEnv *env, Vector<jbyteArray> *buffers, size_t bufferSize);
 
     jobject     mCameraJObjectWeak;     // weak reference to java object
     jclass      mCameraJClass;          // strong reference to java class
     sp<Camera>  mCamera;                // strong reference to native object
     Mutex       mLock;
 
+    /*
+     * Global reference application-managed raw image buffer queue.
+     *
+     * Manual-only mode is supported for raw image callbacks, which is
+     * set whenever method addCallbackBuffer() with msgType =
+     * CAMERA_MSG_RAW_IMAGE is called; otherwise, null is returned
+     * with raw image callbacks.
+     */
+    Vector<jbyteArray> mRawImageCallbackBuffers;
+
+    /*
+     * Application-managed preview buffer queue and the flags
+     * associated with the usage of the preview buffer callback.
+     */
     Vector<jbyteArray> mCallbackBuffers; // Global reference application managed byte[]
     bool mManualBufferMode;              // Whether to use application managed buffers.
-    bool mManualCameraCallbackSet;       // Whether the callback has been set, used to reduce unnecessary calls to set the callback.
+    bool mManualCameraCallbackSet;       // Whether the callback has been set, used to
+                                         // reduce unnecessary calls to set the callback.
 };
 
+bool JNICameraContext::isRawImageCallbackBufferAvailable() const
+{
+    return !mRawImageCallbackBuffers.isEmpty();
+}
+
 sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext)
 {
     sp<Camera> camera;
@@ -128,10 +151,48 @@
         return;
     }
     JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    /*
+     * If the notification or msgType is CAMERA_MSG_RAW_IMAGE_NOTIFY, change it
+     * to CAMERA_MSG_RAW_IMAGE since CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed
+     * to the Java app.
+     */
+    if (msgType == CAMERA_MSG_RAW_IMAGE_NOTIFY) {
+        msgType = CAMERA_MSG_RAW_IMAGE;
+    }
+
     env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
             mCameraJObjectWeak, msgType, ext1, ext2, NULL);
 }
 
+jbyteArray JNICameraContext::getCallbackBuffer(
+        JNIEnv* env, Vector<jbyteArray>* buffers, size_t bufferSize)
+{
+    jbyteArray obj = NULL;
+
+    // Vector access should be protected by lock in postData()
+    if (!buffers->isEmpty()) {
+        LOGV("Using callback buffer from queue of length %d", buffers->size());
+        jbyteArray globalBuffer = buffers->itemAt(0);
+        buffers->removeAt(0);
+
+        obj = (jbyteArray)env->NewLocalRef(globalBuffer);
+        env->DeleteGlobalRef(globalBuffer);
+
+        if (obj != NULL) {
+            jsize bufferLength = env->GetArrayLength(obj);
+            if ((int)bufferLength < (int)bufferSize) {
+                LOGE("Callback buffer was too small! Expected %d bytes, but got %d bytes!",
+                    bufferSize, bufferLength);
+                env->DeleteLocalRef(obj);
+                return NULL;
+            }
+        }
+    }
+
+    return obj;
+}
+
 void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
 {
     jbyteArray obj = NULL;
@@ -141,7 +202,7 @@
         ssize_t offset;
         size_t size;
         sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
-        LOGV("postData: off=%d, size=%d", offset, size);
+        LOGV("copyAndPost: off=%ld, size=%d", offset, size);
         uint8_t *heapBase = (uint8_t*)heap->base();
 
         if (heapBase != NULL) {
@@ -151,32 +212,28 @@
                 LOGV("Allocating callback buffer");
                 obj = env->NewByteArray(size);
             } else {
-                // Vector access should be protected by lock in postData()
-                if(!mCallbackBuffers.isEmpty()) {
-                    LOGV("Using callback buffer from queue of length %d", mCallbackBuffers.size());
-                    jbyteArray globalBuffer = mCallbackBuffers.itemAt(0);
-                    mCallbackBuffers.removeAt(0);
+                switch (msgType) {
+                    case CAMERA_MSG_PREVIEW_FRAME: {
+                        obj = getCallbackBuffer(env, &mCallbackBuffers, size);
 
-                    obj = (jbyteArray)env->NewLocalRef(globalBuffer);
-                    env->DeleteGlobalRef(globalBuffer);
+                        if (mCallbackBuffers.isEmpty()) {
+                            LOGV("Out of buffers, clearing callback!");
+                            mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
+                            mManualCameraCallbackSet = false;
 
-                    if (obj != NULL) {
-                        jsize bufferLength = env->GetArrayLength(obj);
-                        if ((int)bufferLength < (int)size) {
-                            LOGE("Manually set buffer was too small! Expected %d bytes, but got %d!",
-                                 size, bufferLength);
-                            env->DeleteLocalRef(obj);
-                            return;
+                            if (obj == NULL) {
+                                return;
+                            }
                         }
+                        break;
                     }
-                }
-
-                if(mCallbackBuffers.isEmpty()) {
-                    LOGV("Out of buffers, clearing callback!");
-                    mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
-                    mManualCameraCallbackSet = false;
-
-                    if (obj == NULL) {
+                    case CAMERA_MSG_RAW_IMAGE: {
+                        obj = getCallbackBuffer(env, &mRawImageCallbackBuffers, size);
+                        break;
+                    }
+                    default: {
+                        jniThrowException(env,
+                            "java/lang/RuntimeException", "Unsupported message type");
                         return;
                     }
                 }
@@ -212,21 +269,27 @@
     }
 
     // return data based on callback type
-    switch(msgType) {
-    case CAMERA_MSG_VIDEO_FRAME:
-        // should never happen
-        break;
-    // don't return raw data to Java
-    case CAMERA_MSG_RAW_IMAGE:
-        LOGV("rawCallback");
-        env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
-                mCameraJObjectWeak, msgType, 0, 0, NULL);
-        break;
-    default:
-        // TODO: Change to LOGV
-        LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
-        copyAndPost(env, dataPtr, msgType);
-        break;
+    switch (msgType) {
+        case CAMERA_MSG_VIDEO_FRAME:
+            // should never happen
+            break;
+
+        // For backward-compatibility purpose, if there is no callback
+        // buffer for raw image, the callback returns null.
+        case CAMERA_MSG_RAW_IMAGE:
+            LOGV("rawCallback");
+            if (mRawImageCallbackBuffers.isEmpty()) {
+                env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+                        mCameraJObjectWeak, msgType, 0, 0, NULL);
+            } else {
+                copyAndPost(env, dataPtr, msgType);
+            }
+            break;
+
+        default:
+            LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
+            copyAndPost(env, dataPtr, msgType);
+            break;
     }
 }
 
@@ -251,7 +314,7 @@
 
     if (!installed) {
         mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
-        clearCallbackBuffers_l(env);
+        clearCallbackBuffers_l(env, &mCallbackBuffers);
     } else if (mManualBufferMode) {
         if (!mCallbackBuffers.isEmpty()) {
             mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_CAMERA);
@@ -259,24 +322,44 @@
         }
     } else {
         mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_BARCODE_SCANNER);
-        clearCallbackBuffers_l(env);
+        clearCallbackBuffers_l(env, &mCallbackBuffers);
     }
 }
 
-void JNICameraContext::addCallbackBuffer(JNIEnv *env, jbyteArray cbb)
+void JNICameraContext::addCallbackBuffer(
+        JNIEnv *env, jbyteArray cbb, int msgType)
 {
+    LOGV("addCallbackBuffer: 0x%x", msgType);
     if (cbb != NULL) {
         Mutex::Autolock _l(mLock);
-        jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
-        mCallbackBuffers.push(cbb);
+        switch (msgType) {
+            case CAMERA_MSG_PREVIEW_FRAME: {
+                jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
+                mCallbackBuffers.push(callbackBuffer);
 
-        LOGV("Adding callback buffer to queue, %d total", mCallbackBuffers.size());
+                LOGV("Adding callback buffer to queue, %d total",
+                        mCallbackBuffers.size());
 
-        // We want to make sure the camera knows we're ready for the next frame.
-        // This may have come unset had we not had a callbackbuffer ready for it last time.
-        if (mManualBufferMode && !mManualCameraCallbackSet) {
-            mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_CAMERA);
-            mManualCameraCallbackSet = true;
+                // We want to make sure the camera knows we're ready for the
+                // next frame. This may have come unset had we not had a
+                // callbackbuffer ready for it last time.
+                if (mManualBufferMode && !mManualCameraCallbackSet) {
+                    mCamera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_CAMERA);
+                    mManualCameraCallbackSet = true;
+                }
+                break;
+            }
+            case CAMERA_MSG_RAW_IMAGE: {
+                jbyteArray callbackBuffer = (jbyteArray)env->NewGlobalRef(cbb);
+                mRawImageCallbackBuffers.push(callbackBuffer);
+                break;
+            }
+            default: {
+                jniThrowException(env,
+                        "java/lang/IllegalArgumentException",
+                        "Unsupported message type");
+                return;
+            }
         }
     } else {
        LOGE("Null byte array!");
@@ -285,10 +368,15 @@
 
 void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env)
 {
-    LOGV("Clearing callback buffers, %d remained", mCallbackBuffers.size());
-    while(!mCallbackBuffers.isEmpty()) {
-        env->DeleteGlobalRef(mCallbackBuffers.top());
-        mCallbackBuffers.pop();
+    clearCallbackBuffers_l(env, &mCallbackBuffers);
+    clearCallbackBuffers_l(env, &mRawImageCallbackBuffers);
+}
+
+void JNICameraContext::clearCallbackBuffers_l(JNIEnv *env, Vector<jbyteArray> *buffers) {
+    LOGV("Clearing callback buffers, %d remained", buffers->size());
+    while (!buffers->isEmpty()) {
+        env->DeleteGlobalRef(buffers->top());
+        buffers->pop();
     }
 }
 
@@ -458,13 +546,13 @@
     context->setCallbackMode(env, installed, manualBuffer);
 }
 
-static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes) {
-    LOGV("addCallbackBuffer");
+static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) {
+    LOGV("addCallbackBuffer: 0x%x", msgType);
 
     JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
 
     if (context != NULL) {
-        context->addCallbackBuffer(env, bytes);
+        context->addCallbackBuffer(env, bytes, msgType);
     }
 }
 
@@ -492,14 +580,32 @@
     }
 }
 
-static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz)
+static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, int msgType)
 {
     LOGV("takePicture");
     JNICameraContext* context;
     sp<Camera> camera = get_native_camera(env, thiz, &context);
     if (camera == 0) return;
 
-    if (camera->takePicture() != NO_ERROR) {
+    /*
+     * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback
+     * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the
+     * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY
+     * is enabled to receive the callback notification but no data.
+     *
+     * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the
+     * Java application.
+     */
+    if (msgType & CAMERA_MSG_RAW_IMAGE) {
+        LOGV("Enable raw image callback buffer");
+        if (!context->isRawImageCallbackBufferAvailable()) {
+            LOGV("Enable raw image notification, since no callback buffer exists");
+            msgType &= ~CAMERA_MSG_RAW_IMAGE;
+            msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY;
+        }
+    }
+
+    if (camera->takePicture(msgType) != NO_ERROR) {
         jniThrowException(env, "java/lang/RuntimeException", "takePicture failed");
         return;
     }
@@ -638,8 +744,8 @@
   { "setHasPreviewCallback",
     "(ZZ)V",
     (void *)android_hardware_Camera_setHasPreviewCallback },
-  { "addCallbackBuffer",
-    "([B)V",
+  { "_addCallbackBuffer",
+    "([BI)V",
     (void *)android_hardware_Camera_addCallbackBuffer },
   { "native_autoFocus",
     "()V",
@@ -648,7 +754,7 @@
     "()V",
     (void *)android_hardware_Camera_cancelAutoFocus },
   { "native_takePicture",
-    "()V",
+    "(I)V",
     (void *)android_hardware_Camera_takePicture },
   { "native_setParameters",
     "(Ljava/lang/String;)V",
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index fc806a5..667ba75 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -556,6 +556,18 @@
     return doBooleanCommand(cmdstr, "OK");
 }
 
+static void android_net_wifi_enableBackgroundScan(JNIEnv* env, jobject clazz, jboolean enable)
+{
+    //Note: BGSCAN-START and BGSCAN-STOP are documented in core/res/res/values/config.xml
+    //and will need an update if the names are changed
+    if (enable) {
+        doBooleanCommand("DRIVER BGSCAN-START", "OK");
+    }
+    else {
+        doBooleanCommand("DRIVER BGSCAN-STOP", "OK");
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 /*
@@ -623,6 +635,7 @@
         (void*) android_net_wifi_setSuspendOptimizationsCommand},
     { "setCountryCodeCommand", "(Ljava/lang/String;)Z",
         (void*) android_net_wifi_setCountryCodeCommand},
+    { "enableBackgroundScan", "(Z)V", (void*) android_net_wifi_enableBackgroundScan},
 };
 
 int register_android_net_wifi_WifiManager(JNIEnv* env)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1df6fe5..12d7afd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1196,7 +1196,7 @@
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
         android:label="@string/permlab_pkgUsageStats"
         android:description="@string/permdesc_pkgUsageStats"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signatureOrSystem" />
 
     <!-- Allows an application to collect battery statistics -->
     <permission android:name="android.permission.BATTERY_STATS"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0edd33e..ce37943 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -194,6 +194,13 @@
     <!-- Boolean indicating whether the wifi chipset has dual frequency band support -->
     <bool translatable="false" name="config_wifi_dual_band_support">false</bool>
 
+    <!-- Boolean indicating whether the wifi chipset supports background scanning mechanism.
+         This mechanism allows the host to remain in suspend state and the dongle to actively
+         scan and wake the host when a configured SSID is detected by the dongle. This chipset
+         capability can provide power savings when wifi needs to be always kept on.
+         The driver commands needed to support the feature are BGSCAN-START and BGSCAN-STOP -->
+    <bool translatable="false" name="config_wifi_background_scan_support">false</bool>
+
     <!-- Flag indicating whether the keyguard should be bypassed when
          the slider is open.  This can be set or unset depending how easily
          the slider can be opened (for example, in a pocket or purse). -->
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index 1374e7f..41104fe 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -108,15 +108,6 @@
                 fail("thread in sleep is interrupted");
             }
             assertTrue("no uplink data connection after Wi-Fi tethering", mAct.pingTest(null));
-            // Wait for 5 minutes, and verify the data connection again.
-            // bug id: 3400027
-            try {
-                Thread.sleep(5 * 60 * 1000);
-            } catch (Exception e) {
-                fail("thread in sleep is interrupted");
-            }
-            // Verify the uplink data connection
-            assertTrue("no uplink data connection", mAct.pingTest(null));
             // Disable soft AP
             assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false));
             // Wait for 30 seconds until Wi-Fi tethering is stopped
diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/appendix/market-filters.jd
index f826f43..ef1deba 100644
--- a/docs/html/guide/appendix/market-filters.jd
+++ b/docs/html/guide/appendix/market-filters.jd
@@ -24,6 +24,8 @@
 <li><a
 href="{@docRoot}guide/practices/compatibility.html">Android Compatibility</a></li>
 <li><code><a
+href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture&gt;</a></code></li>
+<li><code><a
 href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code></li>
 <li><code><a
 href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code></li>
@@ -395,5 +397,12 @@
 with alternative resources.</p>
     </td>
   </tr>
+  <tr>
+    <td><nobr><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
+&lt;supports-gl-texture&gt;}</a></nobr></td>
+    <td>
+      <p>Android Market filters the application unless one or more of the GL texture compression formats supported by the application are also supported by the device. </p>
+    </td>
+  </tr>
 </table>
 
diff --git a/docs/html/guide/appendix/media-formats.jd b/docs/html/guide/appendix/media-formats.jd
index bac6bf4..8509466 100644
--- a/docs/html/guide/appendix/media-formats.jd
+++ b/docs/html/guide/appendix/media-formats.jd
@@ -168,7 +168,7 @@
 
 
 <tr>
-<td rowspan="3">Video</td>
+<td rowspan="4">Video</td>
 <td>H.263</td>
 <td style="text-align: center;"><big>&bull;</big></td>
 <td style="text-align: center;"><big>&bull;</big></td>
@@ -192,6 +192,14 @@
 <td>3GPP (.3gp)</td>
 </tr>
 
+<tr>
+<td>VP8</td>
+<td>&nbsp;</td>
+<td style="text-align: center;"><big>&bull;</big><br><small>(Android 2.3.3+)</small></td>
+<td>&nbsp;</td>
+<td><a href="http://www.webmproject.org/">WebM</a> (.webm)</td>
+</tr>
+
 </tbody></table>
 
 
diff --git a/docs/html/guide/developing/building/building-cmdline.jd b/docs/html/guide/developing/building/building-cmdline.jd
index 81c1178..5f193bc 100644
--- a/docs/html/guide/developing/building/building-cmdline.jd
+++ b/docs/html/guide/developing/building/building-cmdline.jd
@@ -72,7 +72,7 @@
       <p>This creates your debug <code>.apk</code> file inside the project <code>bin/</code> directory, named
       <code>&lt;your_project_name&gt;-debug.apk</code>. The file is already signed with
       the debug key and has been aligned with
-      <a href="{@docRoot}/guide/developing/tools/zipalign.html"><code>zipalign</code></a>.
+      <a href="{@docRoot}guide/developing/tools/zipalign.html"><code>zipalign</code></a>.
       </p>
     </li>
   </ol>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index d81b416..b13600c 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -60,7 +60,7 @@
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/fundamentals/activities.html">
           <span class="en">Activities</span>
-        </a> <span class="new">new!</span></div>
+        </a> <span class="new-child">new!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/fragments.html">
             <span class="en">Fragments</span>
@@ -69,18 +69,17 @@
             <span class="en">Loaders</span>
           </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/tasks-and-back-stack.html">
-            <span class="en">Tasks and Back Stack</span>
-          </a> <span class="new">new!</span></li>
+            <span class="en">Tasks and Back Stack</span></a></li>
         </ul>
       </li>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/fundamentals/services.html">
           <span class="en">Services</span>
-        </a> <span class="new">new!</span></div>
+        </a></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/bound-services.html">
             <span class="en">Bound Services</span>
-          </a> <span class="new">new!</span></li>
+          </a></li>
         </ul>
       </li>
       <li><a href="<?cs var:toroot ?>guide/topics/providers/content-providers.html">
@@ -91,7 +90,7 @@
           </a></li>
       <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/processes-and-threads.html">
             <span class="en">Processes and Threads</span>
-          </a> <span class="new">new!</span></li>
+          </a></li>
     </ul>
 
 
@@ -100,7 +99,7 @@
         <div><a href="<?cs var:toroot ?>guide/topics/ui/index.html">
             <span class="en">User Interface</span>
           </a>
-          <span class="new">more!</span></div>
+          <span class="new-child">new!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/ui/declaring-layout.html">
                <span class="en">Declaring Layout</span>
@@ -130,10 +129,9 @@
               </a></li>
             </ul>
           </li>
-          <li>
-              <a href="<?cs var:toroot ?>guide/topics/ui/drag-drop.html">
-                  Dragging and Dropping
-              </a><span class="new">new!</span>
+          <li><a href="<?cs var:toroot ?>guide/topics/ui/drag-drop.html">
+                <span class="en">Dragging and Dropping</span>
+              </a> <span class="new">new!</span>
           </li>
           <li><a href="<?cs var:toroot ?>guide/topics/ui/themes.html">
                 <span class="en">Applying Styles and Themes</span>
@@ -225,6 +223,7 @@
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html">&lt;service&gt;</a></li>
+          <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture&gt;</a></li> 
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></li>  <!-- ##api level 4## -->
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></li> <!-- ##api level 4## -->
@@ -240,7 +239,7 @@
         <div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html">
             <span class="en">Graphics</span>
           </a>
-          <span class="new">more!</span></div>
+          <span class="new-child">new!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/graphics/2d-graphics.html">
                 <span class="en">2D Graphics</span>
@@ -250,10 +249,10 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/graphics/renderscript.html">
                 <span class="en">3D with Renderscript</span>
-              </a><span class="new">new!</span></li>
+              </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>guide/topics/graphics/animation.html">
                 <span class="en">Property Animation</span>
-              </a><span class="new">new!</span></li>
+              </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>guide/topics/graphics/view-animation.html">
                 <span class="en">View Animation</span>
               </a></li>
@@ -653,6 +652,9 @@
       <li><a href="<?cs var:toroot ?>guide/practices/screens_support.html">
             <span class="en">Supporting Multiple Screens</span>
           </a></li>
+      <li><a href="<?cs var:toroot ?>guide/practices/optimizing-for-3.0.html">
+            <span class="en">Optimizing Apps for Android 3.0</span>
+          </a> <span class="new">new!</span></li>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/index.html">
                <span class="en">UI Guidelines</span>
diff --git a/docs/html/sdk/android-3.0-optimize.jd b/docs/html/guide/practices/optimizing-for-3.0.jd
similarity index 100%
rename from docs/html/sdk/android-3.0-optimize.jd
rename to docs/html/guide/practices/optimizing-for-3.0.jd
diff --git a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
index 7f35b04..31ad466 100644
--- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
@@ -1,4 +1,6 @@
 page.title=Activity and Task Design Guidelines
+parent.title=UI Guidelines
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd
index 840ee66..7751a7b 100644
--- a/docs/html/guide/practices/ui_guidelines/menu_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd
@@ -1,4 +1,6 @@
 page.title=Menu Design Guidelines
+parent.title=UI Guidelines
+parent.link=index.html
 @jd:body
 	
 <div id="qv-wrapper">
diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd
index e978069..49aa498 100644
--- a/docs/html/guide/practices/ui_guidelines/widget_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd
@@ -1,4 +1,6 @@
 page.title=Widget Design Guidelines
+parent.title=UI Guidelines
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/graphics/renderscript.jd b/docs/html/guide/topics/graphics/renderscript.jd
index 0e64c78..60bffdb 100644
--- a/docs/html/guide/topics/graphics/renderscript.jd
+++ b/docs/html/guide/topics/graphics/renderscript.jd
@@ -115,7 +115,7 @@
     <code><em>ScriptC_renderscript_filename</em></code>.
     Accessor methods are generated, so the Android system layer can access the values.
     The <code>get</code> method comes with a one-way communication restriction. 
-    The Android system layer always caches the last value that is set and returns that during a call to a <code>get<code> method.
+    The Android system layer always caches the last value that is set and returns that during a call to a <code>get</code> method.
     If the native Renderscript code changes the value, the change does not propagate back to the Android system layer.
     If the global variables are initialized in the native Renderscript code, those values are used
     to initialize the corresponding values in the Android system. If global variables are marked as <code>const</code>,
@@ -373,11 +373,11 @@
         graphics context by calling 
         {@link android.renderscript.RenderScriptGL#bindProgramVertex bindProgramVertex()}. It is then used for all
         subsequent draw calls until you bind a new program. If the program has constant inputs, the
-        user needs to bind an allocation containing those inputs. The allocation’s type must match
+        user needs to bind an allocation containing those inputs. The allocation's type must match
         the one provided during creation. The Renderscript library then does all the necessary
         plumbing to send those constants to the graphics hardware. Varying inputs to the shader,
         such as position, normal, and texture coordinates are matched by name between the input
-        Element and the Mesh object being drawn. The signatures don’t have to be exact or in any
+        Element and the Mesh object being drawn. The signatures don't have to be exact or in any
         strict order. As long as the input name in the shader matches a channel name and size
         available on the mesh, the run-time would take care of connecting the two. Unlike OpenGL,
         there is no need to link the vertex and fragment programs.</p>
@@ -396,7 +396,7 @@
       <td>rs_program_fragment</td>
 
       <td><p>The Renderscript fragment program, also known as the fragment shader, is responsible for
-      manipulating pixel data in a user-defined way. It’s constructed from a GLSL shader string
+      manipulating pixel data in a user-defined way. It's constructed from a GLSL shader string
       containing the program body, textures inputs, and a Type object describing the constants used
       by the program. Like the vertex programs, when an allocation with constant input values is
       bound to the shader, its values are sent to the graphics program automatically. Note that the
@@ -445,7 +445,7 @@
       mip-maps are used and the amount of anisotropy required. There may be situations where
       hardware limitations prevent the exact behavior from being matched. In these cases, the
       runtime attempts to provide the closest possible approximation. For example, the user
-      requested 16x anisotropy, but only 8x was set because it’s the best available on the
+      requested 16x anisotropy, but only 8x was set because it's the best available on the
       hardware.</td>
     </tr>
 
diff --git a/docs/html/guide/topics/manifest/action-element.jd b/docs/html/guide/topics/manifest/action-element.jd
index d7ba78d..8ad94cd 100644
--- a/docs/html/guide/topics/manifest/action-element.jd
+++ b/docs/html/guide/topics/manifest/action-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;action&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/activity-alias-element.jd b/docs/html/guide/topics/manifest/activity-alias-element.jd
index 4521b4b..ba2c154 100644
--- a/docs/html/guide/topics/manifest/activity-alias-element.jd
+++ b/docs/html/guide/topics/manifest/activity-alias-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;activity-alias&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 5e0b536..c910686 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;activity&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
@@ -14,6 +16,7 @@
           android:<a href="#exclude">excludeFromRecents</a>=["true" | "false"]
           android:<a href="#exported">exported</a>=["true" | "false"]
           android:<a href="#finish">finishOnTaskLaunch</a>=["true" | "false"]
+          android:<a href="#hwaccel">hardwareAccelerated</a>=["true" | "false"]
           android:<a href="#icon">icon</a>="<i>drawable resource</i>"
           android:<a href="#label">label</a>="<i>string resource</i>"
           android:<a href="#lmode">launchMode</a>=["multiple" | "singleTop" |
@@ -286,6 +289,24 @@
 activity is ignored.  The activity is not re-parented, but destroyed.
 </p>
 
+<dt><a name="hwaccel"></a>{@code android:hardwareAccelerated}</dt>
+<dd>Whether or not hardware-accelerated rendering should be enabled for this
+Activity &mdash; "{@code true}" if it should be enabled, and "{@code false}" if
+not. The default value is "{@code false}".
+
+<p>Starting from Android 3.0, a hardware-accelerated OpenGL renderer is
+available to applications, to improve performance for many common 2D graphics
+operations. When the hardware-accelerated renderer is enabled, most operations
+in Canvas, Paint, Xfermode, ColorFilter, Shader, and Camera are accelerated.
+This results in smoother animations, smoother scrolling, and improved
+responsiveness overall, even for applications that do not explicitly make use
+the framework's OpenGL libraries. </p>
+
+<p>Note that not all of the OpenGL 2D operations are accelerated. If you enable
+the hardware-accelerated renderer, test your application to ensure that it can
+make use of the renderer without errors.</p>
+</dd>
+
 <dt><a name="icon"></a>{@code android:icon}</dt>
 <dd>An icon representing the activity. The icon is displayed to users when 
 a representation of the activity is required on-screen.  For example, icons 
diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd
index 1fadc6e..41313ed 100644
--- a/docs/html/guide/topics/manifest/application-element.jd
+++ b/docs/html/guide/topics/manifest/application-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;application&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
@@ -9,6 +11,7 @@
              android:<a href="#desc">description</a>="<i>string resource</i>"
              android:<a href="#enabled">enabled</a>=["true" | "false"]
              android:<a href="#code">hasCode</a>=["true" | "false"]
+             android:<a href="#hwaccel">hardwareAccelerated</a>=["true" | "false"]
              android:<a href="#icon">icon</a>="<i>drawable resource</i>"
              android:<a href="#killrst">killAfterRestore</a>=["true" | "false"]
              android:<a href="#label">label</a>="<i>string resource</i>"
@@ -108,7 +111,26 @@
 <p>
 An application would not have any code of its own only if it's using nothing
 but built-in component classes, such as an activity that uses the {@link 
-android.app.AliasActivity} class, a rare occurrence.
+android.app.AliasActivity} class, a rare occurrence.</p>
+</dd>
+
+<dt><a name="hwaccel"></a>{@code android:hardwareAccelerated}</dt>
+<dd>Whether or not hardware-accelerated rendering should be enabled for all
+Activities and Views in this application &mdash; "{@code true}" if it
+should be enabled, and "{@code false}" if not. The default value is "{@code false}".
+
+<p>Starting from Android 3.0, a hardware-accelerated OpenGL renderer is
+available to applications, to improve performance for many common 2D graphics
+operations. When the hardware-accelerated renderer is enabled, most operations
+in Canvas, Paint, Xfermode, ColorFilter, Shader, and Camera are accelerated.
+This results in smoother animations, smoother scrolling, and improved
+responsiveness overall, even for applications that do not explicitly make use
+the framework's OpenGL libraries. </p>
+
+<p>Note that not all of the OpenGL 2D operations are accelerated. If you enable
+the hardware-accelerated renderer, test your application to ensure that it can
+make use of the renderer without errors.</p>
+</dd>
 
 <dt><a name="icon"></a>{@code android:icon}</dt>
 <dd>An icon for the application as whole, and the default icon for 
diff --git a/docs/html/guide/topics/manifest/category-element.jd b/docs/html/guide/topics/manifest/category-element.jd
index b9a1aa6..f392c0a 100644
--- a/docs/html/guide/topics/manifest/category-element.jd
+++ b/docs/html/guide/topics/manifest/category-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;category&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/compatible-screens-element.jd b/docs/html/guide/topics/manifest/compatible-screens-element.jd
index 9fb0fd2..8669874 100644
--- a/docs/html/guide/topics/manifest/compatible-screens-element.jd
+++ b/docs/html/guide/topics/manifest/compatible-screens-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;compatible-screens&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/data-element.jd b/docs/html/guide/topics/manifest/data-element.jd
index b77fd05..9b0d0df 100644
--- a/docs/html/guide/topics/manifest/data-element.jd
+++ b/docs/html/guide/topics/manifest/data-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;data&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/grant-uri-permission-element.jd b/docs/html/guide/topics/manifest/grant-uri-permission-element.jd
index 9dafe85..dc98cbb 100644
--- a/docs/html/guide/topics/manifest/grant-uri-permission-element.jd
+++ b/docs/html/guide/topics/manifest/grant-uri-permission-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;grant-uri-permission&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/instrumentation-element.jd b/docs/html/guide/topics/manifest/instrumentation-element.jd
index b18e777..9408b84 100644
--- a/docs/html/guide/topics/manifest/instrumentation-element.jd
+++ b/docs/html/guide/topics/manifest/instrumentation-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;instrumentation&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/intent-filter-element.jd b/docs/html/guide/topics/manifest/intent-filter-element.jd
index 2b1322c..d293400 100644
--- a/docs/html/guide/topics/manifest/intent-filter-element.jd
+++ b/docs/html/guide/topics/manifest/intent-filter-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;intent-filter&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index 7f21e6b..a8125b3 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;manifest&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/manifest-intro.jd b/docs/html/guide/topics/manifest/manifest-intro.jd
index d7a3e3e..0f20305 100644
--- a/docs/html/guide/topics/manifest/manifest-intro.jd
+++ b/docs/html/guide/topics/manifest/manifest-intro.jd
@@ -83,6 +83,8 @@
     <a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration /&gt;</a>  <!-- ##api level 3## -->
     <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature /&gt;</a>  <!-- ##api level 4## -->
     <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens /&gt;</a>  <!-- ##api level 4## -->
+    <a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">&lt;compatible-screens /&gt;</a>  <!-- ##api level 9## -->
+    <a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture /&gt;</a>  <!-- ##api level 11## -->
 
     <a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a>
 
diff --git a/docs/html/guide/topics/manifest/meta-data-element.jd b/docs/html/guide/topics/manifest/meta-data-element.jd
index 101b05a..85a871d 100644
--- a/docs/html/guide/topics/manifest/meta-data-element.jd
+++ b/docs/html/guide/topics/manifest/meta-data-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;meta-data&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/path-permission-element.jd b/docs/html/guide/topics/manifest/path-permission-element.jd
index 5c271a7..e644d68 100644
--- a/docs/html/guide/topics/manifest/path-permission-element.jd
+++ b/docs/html/guide/topics/manifest/path-permission-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;path-permission&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/permission-element.jd b/docs/html/guide/topics/manifest/permission-element.jd
index ad64d5d..c256fb1 100644
--- a/docs/html/guide/topics/manifest/permission-element.jd
+++ b/docs/html/guide/topics/manifest/permission-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;permission&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/permission-group-element.jd b/docs/html/guide/topics/manifest/permission-group-element.jd
index 0ad76a6..fc1de1f 100644
--- a/docs/html/guide/topics/manifest/permission-group-element.jd
+++ b/docs/html/guide/topics/manifest/permission-group-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;permission-group&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/permission-tree-element.jd b/docs/html/guide/topics/manifest/permission-tree-element.jd
index 6d6cd0a..a9c00cd 100644
--- a/docs/html/guide/topics/manifest/permission-tree-element.jd
+++ b/docs/html/guide/topics/manifest/permission-tree-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;permission-tree&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/provider-element.jd b/docs/html/guide/topics/manifest/provider-element.jd
index c80b207..dd00224 100644
--- a/docs/html/guide/topics/manifest/provider-element.jd
+++ b/docs/html/guide/topics/manifest/provider-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;provider&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/receiver-element.jd b/docs/html/guide/topics/manifest/receiver-element.jd
index b208917..7012c0f 100644
--- a/docs/html/guide/topics/manifest/receiver-element.jd
+++ b/docs/html/guide/topics/manifest/receiver-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;receiver&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/service-element.jd b/docs/html/guide/topics/manifest/service-element.jd
index 0a44e2c..d9a81b3 100644
--- a/docs/html/guide/topics/manifest/service-element.jd
+++ b/docs/html/guide/topics/manifest/service-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;service&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/supports-gl-texture-element.jd b/docs/html/guide/topics/manifest/supports-gl-texture-element.jd
new file mode 100644
index 0000000..6c4a05a
--- /dev/null
+++ b/docs/html/guide/topics/manifest/supports-gl-texture-element.jd
@@ -0,0 +1,189 @@
+page.title=&lt;supports-gl-texture&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
+@jd:body
+
+<dl class="xml">
+
+<dt>syntax:</dt>
+<dd>
+<pre class="stx">
+&lt;supports-gl-texture android:<a href="#name">name</a>="<em>string</em>" /&gt;
+</pre>
+</dd>
+
+<dt>contained in:</dt>
+<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
+
+ <div class="sidebox-wrapper">
+  <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
+  <div id="qv-sub-rule">
+    <img src="{@docRoot}assets/images/icon_market.jpg"
+    style="float:left;margin:0;padding:0;">
+    <p style="color:#669999;">Android Market and <code
+    style="color:#669999;">&lt;supports-gl-texture&gt;</code> elements</p>
+    <p style="margin-top:1em;">Android Market filters applications according
+    to the texture compression formats that they support, to ensure that
+    they can be installed only on devices that can handle their textures
+    properly. Developers can use texture compression filtering
+    as a way of targeting specific device types, based on GPU platform.</p>
+    
+    <p style="margin-top:1em;" class="caution">For important information about how
+    Android Market uses <code>&lt;supports-gl-texture&gt;</code> elements as
+    the basis for filtering, please read <a href="#market-texture-filtering">Android
+    Market and texture compression filtering</a>, below.</p>
+</div> 
+</div>
+
+<dt>description:</dt>
+<dd>Declares a single GL texture compression format that is supported by
+the application.
+
+<p>An application "supports" a GL texture compression format if it is capable of
+providing texture assets that are compressed in that format, once the
+application is installed on a device. The application can provide the
+compressed assets locally, from inside the <code>.apk</code>, or it can download them
+from a server at runtime.</p>
+
+<p>Each <code>&lt;supports-gl-texture&gt;</code> element declares exactly one
+supported texture compression format, specified as the value of a
+<code>android:name</code> attribute. If your application supports multiple
+texture compression formats, you can declare multiple
+<code>&lt;supports-gl-texture&gt;</code> elements. For example:</p>
+
+<pre>&lt;supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" /&gt;
+&lt;supports-gl-texture android:name="GL_OES_compressed_paletted_texture" /&gt;</pre>
+
+<p>Declared <code>&lt;supports-gl-texture&gt;</code> elements are informational,
+meaning that the Android system itself does not examine the elements at install
+time to ensure matching support on the device. However, other services
+(such as Android Market) or applications can check your application's
+<code>&lt;supports-gl-texture&gt;</code> declarations as part of handling or
+interacting with your application. For this reason, it's very important that
+you declare all of the texture compression formats (from the list below) that
+your application is capable of supporting. </p>
+
+<p>Applications and devices typically declare their supported GL texture
+compression formats using the same set of well-known strings, as listed below.
+The set of format strings may grow over time, as needed, and since the values
+are strings, applications are free to declare other formats as needed.</p>
+
+<p>Assuming that the application is built with SDK Platform Tools r3 or higher,
+filtering based on the <code>&lt;supports-gl-texture></code> element is activated
+for all API levels.</p>
+
+<dt>attributes:</dt>
+
+<dd>
+<dl class="attr">
+
+  <dt><a name="name"></a>{@code android:name}</dt>
+  <dd>Specifies a single GL texture compression format supported by the application,
+  as a descriptor string. Common descriptor values are listed in the table below.
+
+<table>
+<tr>
+<th>Texture Compression Format Descriptor</th>
+<th>Comments</th>
+</tr>
+<tr>
+<td><code>GL_OES_compressed_ETC1_RGB8_texture</code></td>
+<td>Ericsson texture compression. Specified in OpenGL ES 2.0 and available in all
+Android-powered devices that support OpenGL ES 2.0.</td>
+</tr>
+<tr>
+<td><code>GL_OES_compressed_paletted_texture</code></td>
+<td>Generic paletted texture compression.</td>
+</tr>
+<tr>
+<td><code>GL_AMD_compressed_3DC_texture</code></td>
+<td>ATI 3Dc texture compression. </td>
+</tr>
+<tr>
+<td><code>GL_AMD_compressed_ATC_texture</code></td>
+<td>ATI texture compression. Available on devices running Adreno GPU, including
+HTC Nexus One, Droid Incredible, EVO, and others. For widest compatibility,
+devices may also declare a <code>&lt;supports-gl-texture&gt;</code> element with the
+descriptor <code>GL_ATI_texture_compression_atitc</code>. </td>
+</tr>
+<tr>
+<td><code>GL_EXT_texture_compression_latc</code></td>
+<td>Luminance alpha texture compression. </td>
+</tr>
+<tr>
+<td><code>GL_EXT_texture_compression_dxt1</code></td>
+<td>S3 DXT1 texture compression. Supported on devices running Nvidia Tegra2
+platform, including Motorala Xoom, Motorola Atrix, Droid Bionic, and
+others.</td>
+</tr>
+<tr>
+<td><code>GL_EXT_texture_compression_s3tc</code></td>
+<td>S3 texture compression, nonspecific to DXT variant. Supported on devices
+running Nvidia Tegra2 platform, including Motorala Xoom, Motorola Atrix, Droid
+Bionic, and others. If your application requires a specific DXT variant, declare
+that descriptor instead of this one.</td>
+</tr>
+<tr>
+<td><code>GL_IMG_texture_compression_pvrtc</code></td>
+<td>PowerVR texture compression. Available in devices running PowerVR SGX530/540
+GPU, such as Motorola DROID series; Samsung Galaxy S, Nexus S, and Galaxy Tab;
+and others.</td>
+</tr>
+</table>
+
+</dd>
+</dl></dd>
+
+<!-- ##api level indication##
+<dt>introduced in:</dt>
+<dd>API Level </dd>-->
+
+<dt>see also:</dt>
+<dd>
+  <ul>
+    <li><a href="{@docRoot}guide/appendix/market-filters.html">Android Market Filters</a></li>
+  </ul>
+</dd>
+
+<h2 id="market-texture-filtering">Android Market and texture compression filtering</h2>
+
+<p>Android Market filters the applications that are visible to users, so that
+users can see and download only those applications that are compatible with
+their devices. One of the ways Market filters applications is by texture
+compression compatibility, giving you control over the availability of your
+application to various devices, based on the capabilities of their GPUs.</p>
+
+<p>To determine an application's texture compression compatibility with a given
+user's device, Android Market compares:</p>
+
+<ul>
+<li>Texture compression formats that are supported by the application &mdash;
+an application declares its supported texture compression formats in
+<code>&lt;supports-gl-texture&gt;</code> elements in its manifest <br/>with...</li>
+<li>Texture compression formats that are supported by the GPU on the device &mdash;
+a device reports the formats it supports as read-only system properties.</li>
+</ul>
+
+<p>Each time you upload an application to the Android Market Publisher Site,
+Android Market scans the application's manifest file and looks for any
+<code>&lt;supports-gl-texture&gt;</code> elements. It extracts the
+format descriptors from the elements and stores them internally as
+metadata associated with the application <code>.apk</code> and the application
+version. </p>
+
+<p>When a user searches or browses for applications on Android Market,
+the service compares the texture compression formats supported by the application
+with those supported by the user's device. The comparison is based on the format
+descriptor strings and a match must be exact.</p>
+
+<p>If <em>any</em> of an application's supported texture compression formats is
+also supported by the device, Android Market allows the user to see the
+application and potentially download it. Otherwise, if none of the application's
+formats is supported by the device, Android Market filters the application so
+that it is not available for download. </p>
+
+<p>If an application does not declare any <code>&lt;supports-gl-texture&gt;</code> elements,
+Android Market does not apply any filtering based on GL texture compression format.</p>
+
+</dl>
+
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index 92c769e..ee99a37 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;supports-screens&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/uses-configuration-element.jd b/docs/html/guide/topics/manifest/uses-configuration-element.jd
index 4578c63..20ec85f 100755
--- a/docs/html/guide/topics/manifest/uses-configuration-element.jd
+++ b/docs/html/guide/topics/manifest/uses-configuration-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;uses-configuration&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <!-- ##api level 3##  see comment below -->
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 0828e8b..fec6a98 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;uses-feature&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/uses-library-element.jd b/docs/html/guide/topics/manifest/uses-library-element.jd
index 1d38c1a..d94ad9f 100644
--- a/docs/html/guide/topics/manifest/uses-library-element.jd
+++ b/docs/html/guide/topics/manifest/uses-library-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;uses-library&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
@@ -44,7 +46,7 @@
         <dd>
             Android Market filters applications based on the libraries installed on the
             user's device. For more information about filtering, see the topic
-            <a href="{@docRoot}/guide/appendix/market-filters.html">Market Filters</a>.
+            <a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>.
         </dd>
     </dl>
     <p>
diff --git a/docs/html/guide/topics/manifest/uses-permission-element.jd b/docs/html/guide/topics/manifest/uses-permission-element.jd
index 085b9f0..967fc5a 100644
--- a/docs/html/guide/topics/manifest/uses-permission-element.jd
+++ b/docs/html/guide/topics/manifest/uses-permission-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;uses-permission&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd
index 971d4cb..b371f34 100644
--- a/docs/html/guide/topics/manifest/uses-sdk-element.jd
+++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd
@@ -1,4 +1,6 @@
 page.title=&lt;uses-sdk&gt;
+parent.title=The AndroidManifest.xml File
+parent.link=manifest-intro.html
 @jd:body
 
 <dl class="xml">
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
index c33c507..0329c192 100644
--- a/docs/html/guide/topics/ui/drag-drop.jd
+++ b/docs/html/guide/topics/ui/drag-drop.jd
@@ -1,5 +1,8 @@
 page.title=Dragging and Dropping
+parent.title=User Interface
+parent.link=index.html
 @jd:body
+
 <div id="qv-wrapper">
     <div id="qv">
         <h2>Quickview</h2>
diff --git a/docs/html/guide/topics/ui/notifiers/index.jd b/docs/html/guide/topics/ui/notifiers/index.jd
index d29324c..8fc57fc 100644
--- a/docs/html/guide/topics/ui/notifiers/index.jd
+++ b/docs/html/guide/topics/ui/notifiers/index.jd
@@ -1,4 +1,6 @@
 page.title=Notifying the User
+parent.title=User Interface
+parent.link=../index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/resources/community-more.jd b/docs/html/resources/community-more.jd
index 9f16fea..df72926 100644
--- a/docs/html/resources/community-more.jd
+++ b/docs/html/resources/community-more.jd
@@ -24,7 +24,11 @@
 </tr>
 </table>
 
-<p>If you haven't used IRC before, check <a href="http://en.wikipedia.org/wiki/List_of_IRC_clients">http://en.wikipedia.org/wiki/List_of_IRC_clients &raquo;</a> for a helpful list of IRC clients. Alternatively, you could also use this <a href="http://java.freenode.net/index.php?channel=android-dev">web interface &raquo;</a>, which does not require any installation, to join discussions on the Android IRC channels.  </p>
+<p>If you haven't used IRC before, check <a
+href="http://en.wikipedia.org/wiki/List_of_IRC_clients">http://en.wikipedia.org/wiki/
+List_of_IRC_clients &raquo;</a> for a helpful list of IRC clients. Alternatively, you could also use
+this <a href="http://webchat.freenode.net/?channels=android-dev">web interface &raquo;</a>, which
+does not require any installation, to join discussions on the Android IRC channels.  </p>
 
 <p>Here are some tips for using IRC:</h4>
 
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index b80e59a..e919de9 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -496,7 +496,7 @@
     }
   },
   {
-    tags: ['sample', 'new'],
+    tags: ['sample', 'new', 'newfeature', 'performance', 'gamedev', 'gl'],
     path: 'samples/Renderscript/index.html',
     title: {
       en: 'Renderscript'
diff --git a/docs/html/sdk/android-3.0-highlights.jd b/docs/html/sdk/android-3.0-highlights.jd
index 591f088..ebeb3789 100644
--- a/docs/html/sdk/android-3.0-highlights.jd
+++ b/docs/html/sdk/android-3.0-highlights.jd
@@ -46,7 +46,9 @@
 <p>Welcome to Android 3.0!</p>
 
 <p>The Android 3.0 platform introduces many new and exciting features for users and developers. 
-This document provides a glimpse of some of the new features and technologies, as delivered in the Android 3.0 Preview SDK. For more information about the SDK or how to download it, please see the <a href="{@docRoot}sdk/preview/index.html">Preview SDK</a> document.</p>
+This document provides a glimpse of some of the new features and technologies, as delivered in
+Android 3.0. For a more detailed look at new developer APIs, see the <a
+href="{@docRoot}sdk/android-3.0.html">Android 3.0 Platform</a> document.</p>
 
 <ul>
   <li><a href="#UserFeatures">New User Features</a></li>
@@ -259,7 +261,8 @@
 </object>
 </div>
 
-<p>For more information about the new developer APIs, see the Android 3.0 Platform notes in the SDK Preview documentation, available by download through the Android SDK Manager.</p>
+<p>For more information about the new developer APIs, see the <a
+href="{@docRoot}sdk/android-3.0.html">Android 3.0 Platform</a> document.</p>
 
 <p>For a video overview of platform features, see the Android 3.0 Sneak Peek. </p>
 
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index 6c88146..6c087bb 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -1,4 +1,4 @@
-page.title=Android 3.0 Platform Preview
+page.title=Android 3.0 Platform
 sdk.platform.version=3.0
 sdk.platform.apiLevel=11
 @jd:body
@@ -25,7 +25,7 @@
 
 <h2>See Also</h2>
 <ol>
-  <li><a href="{@docRoot}sdk/android-3.0-optimize.html">Optimizing Apps for Android 3.0</a></li>
+  <li><a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android 3.0</a></li>
 </ol>
 
 </div>
@@ -48,10 +48,12 @@
 href="{@docRoot}sdk/android-{@sdkPlatformVersion}-highlights.html">Platform
 Highlights</a>.</p>
 
-<p>Also see the <a href="{@docRoot}sdk/android-3.0-optimize.html">Optimizing Apps for Android
-3.0</a> document for information about how to optimize your existing applications for Android 3.0
-devices, even if you want to remain compatible with previous versions.</p>
-
+<p class="note"><strong>Note:</strong>
+If you've already published an Android application, please test and optimize your application on
+Android 3.0 as soon as possible. You should do so to be sure your application provides the best
+experience possible on the latest Android-powered devices. For information about what you can do,
+read <a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android
+3.0</a>.</p>
 
 
 <h2 id="relnotes">Revisions</h2>
@@ -866,8 +868,8 @@
 <h3>JSON utilities</h3>
 
 <p>New classes, {@link android.util.JsonReader} and {@link android.util.JsonWriter}, help you
-read and write JSON streams. The new APIs compliment the {@link org.json} classes which manipulate a
-document in memory.</p>
+read and write JSON streams. The new APIs complement the {@link org.json} classes, which manipulate
+a document in memory.</p>
 
 <p>You can create an instance of {@link android.util.JsonReader} by calling
 its constructor method and passing the {@link java.io.InputStreamReader} that feeds the JSON string.
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index df8869e..7f6f0105 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -2,20 +2,20 @@
 sdk.redirect=0
 
 sdk.win_installer=installer_r10-windows.exe
-sdk.win_installer_bytes=32845713
-sdk.win_installer_checksum=4e4356c472a6271ac9c062df0219dcb3
+sdk.win_installer_bytes=32878481
+sdk.win_installer_checksum=8ffa2dd734829d0bbd3ea601b50b36c7
 
 sdk.win_download=android-sdk_r10-windows.zip
-sdk.win_bytes=30112516
-sdk.win_checksum=643a75d99f5d4ca39dcf743fe894d599
+sdk.win_bytes=32832260
+sdk.win_checksum=1e42b8f528d9ca6d9b887c58c6f1b9a2
 
 sdk.mac_download=android-sdk_r10-mac_x86.zip
-sdk.mac_bytes=28224540
-sdk.mac_checksum=4d0a99a458e4f4bde65a01f8545f27e9
+sdk.mac_bytes=28847132
+sdk.mac_checksum=e3aa5578a6553b69cc36659c9505be3f
 
 sdk.linux_download=android-sdk_r10-linux_x86.tgz
-sdk.linux_bytes=26556013
-sdk.linux_checksum=10cafdd44771bfe2ba9d4440886389e7
+sdk.linux_bytes=26981997
+sdk.linux_checksum=c022dda3a56c8a67698e6a39b0b1a4e0
 
 @jd:body
 
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index 40231a3..bc9ba4b 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -1,16 +1,16 @@
 ndk=true
 
-ndk.win_download=android-ndk-r6-windows.zip
-ndk.win_bytes=64147764
-ndk.win_checksum=771b56328b7fc7751aa8040fb9dd09f0
+ndk.win_download=android-ndk-r5b-windows.zip
+ndk.win_bytes=61299831
+ndk.win_checksum=87745ada305ab639399161ab4faf684c
 
-ndk.mac_download=android-ndk-r6-darwin-x86.tar.bz2
-ndk.mac_bytes=50244722
-ndk.mac_checksum=d107f6d63478b73e09ed2eecd4c62bd3
+ndk.mac_download=android-ndk-r5b-darwin-x86.tar.bz2
+ndk.mac_bytes=50210863
+ndk.mac_checksum=019a14622a377b3727ec789af6707037
 
-ndk.linux_download=android-ndk-r6-linux-x86.tar.bz2
-ndk.linux_bytes=44088689
-ndk.linux_checksum=c83c3ab5a5e5a3b3fe7b907735ce77d4
+ndk.linux_download=android-ndk-r5b-linux-x86.tar.bz2
+ndk.linux_bytes=44138539
+ndk.linux_checksum=4c0045ddc2bfd657be9d5177d0e0b7e7
 
 page.title=Android NDK
 @jd:body
@@ -61,55 +61,6 @@
 
 <div class="toggleable open">
     <a href="#"
-         onclick="return toggleDiv(this)"><img src="{@docRoot}assets/images/triangle-opened.png"
-         class="toggle-img"
-         height="9px"
-         width="9px" /> Android NDK, Revision 6</a> <em>(February 2011)</em>
-
-    <div class="toggleme">
-      <p>This release of the NDK introduces the following header files:</p>
-        <ul>
-          <li><p><code>&lt;android/asset_manager.h&gt;</code>: Allows access to assets
-          using 64-bit file offsets and sizes. This is useful for very large assets that exceed
-          2GB, as required by some games. The following APIs are provided:<p>
-              <ul>
-                <li><code>AAsset_getLength64</code></li>
-                <li><code>AAsset_getRemainingLength64</code></li>
-                <li><code>AAsset_openFileDescriptor64</code></li>
-                <li><code>AAsset_seek64</code></li>
-              </ul>
-          </li>
-          
-          <li><code>&lt;android/input.h&gt;</code>: Provides the following AMETA_XXX constants 
-          that are related to the new input framework in Honeycomb:
-<pre>              
-AMETA_FUNCTION_ON = 0x08,
-AMETA_CTRL_ON = 0x1000,
-AMETA_CTRL_LEFT_ON = 0x2000,
-AMETA_CTRL_RIGHT_ON = 0x4000,
-AMETA_META_ON = 0x10000,
-AMETA_META_LEFT_ON = 0x20000,
-AMETA_META_RIGHT_ON = 0x40000,
-AMETA_CAPS_LOCK_ON = 0x100000,
-AMETA_NUM_LOCK_ON = 0x200000,
-AMETA_SCROLL_LOCK_ON = 0x400000,
-</pre>
-          </li>
-          
-          <li><code>&lt;android/keycodes&gt;</code>: Provides <code>AKEYCODE_XXX</code>
-          constants that are related to the new input framework in Honeycomb.
-          </li>
-          
-          <li><code>&lt;android/native_activity.h&gt;</code>: Adds a new field to the
-          system-allocated <code>ANativeActivity</code> structure named <code>obbPath</code> that
-          contains the path of your application's OBB files, if any.
-          </li>
-  </ul>
-  </div>
-  </div>
-
-<div class="toggleable closed">
-    <a href="#"
          onclick="return toggleDiv(this)"><img src="{@docRoot}assets/images/triangle-closed.png"
          class="toggle-img"
          height="9px"
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index c1894d8..a1c26db 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -80,7 +80,6 @@
         <div><a href="<?cs var:toroot ?>sdk/android-3.0.html">
         <span class="en">Android 3.0 Platform</span></a> <span class="new">new!</span></div>
         <ul>
-          <li><a href="<?cs var:toroot ?>sdk/android-3.0-optimize.html">Optimizing Apps for 3.0</a></li> 
           <li><a href="<?cs var:toroot ?>sdk/android-3.0-highlights.html">Platform Highlights</a></li> 
           <li><a href="<?cs var:toroot ?>sdk/api_diff/11/changes.html">API Differences Report &raquo;</a></li>
         </ul>
@@ -152,8 +151,8 @@
       <span style="display:none" class="zh-TW"></span>
     </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6</a>
-        <span class="new">new!</span></li>
+      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5b</a>
+        </li>
       <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
     </ul>
   </li>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index cffee5f..8d17561 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -240,7 +240,7 @@
         /**
          * The resulting height of the bitmap, set independent of the state of
          * inJustDecodeBounds. However, if there is an error trying to decode,
-         * outHeight will be set to -1.
+         * outHeight will be set to -1. 
          */
         public int outHeight;
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 65c6ccf..2089751 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -811,11 +811,12 @@
                         com.android.internal.R.styleable.DrawableCorners_bottomRightRadius, radius);
                 if (topLeftRadius != radius || topRightRadius != radius ||
                         bottomLeftRadius != radius || bottomRightRadius != radius) {
+                    // The corner radii are specified in clockwise order (see Path.addRoundRect())
                     setCornerRadii(new float[] {
                             topLeftRadius, topLeftRadius,
                             topRightRadius, topRightRadius,
-                            bottomLeftRadius, bottomLeftRadius,
-                            bottomRightRadius, bottomRightRadius
+                            bottomRightRadius, bottomRightRadius,
+                            bottomLeftRadius, bottomLeftRadius
                     });
                 }
                 a.recycle();
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index e5f7e62..f3c8f64 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -66,16 +66,17 @@
 
 // msgType in notifyCallback and dataCallback functions
 enum {
-    CAMERA_MSG_ERROR            = 0x001,
-    CAMERA_MSG_SHUTTER          = 0x002,
-    CAMERA_MSG_FOCUS            = 0x004,
-    CAMERA_MSG_ZOOM             = 0x008,
-    CAMERA_MSG_PREVIEW_FRAME    = 0x010,
-    CAMERA_MSG_VIDEO_FRAME      = 0x020,
-    CAMERA_MSG_POSTVIEW_FRAME   = 0x040,
-    CAMERA_MSG_RAW_IMAGE        = 0x080,
-    CAMERA_MSG_COMPRESSED_IMAGE = 0x100,
-    CAMERA_MSG_ALL_MSGS         = 0x1FF
+    CAMERA_MSG_ERROR            = 0x0001,
+    CAMERA_MSG_SHUTTER          = 0x0002,
+    CAMERA_MSG_FOCUS            = 0x0004,
+    CAMERA_MSG_ZOOM             = 0x0008,
+    CAMERA_MSG_PREVIEW_FRAME    = 0x0010,
+    CAMERA_MSG_VIDEO_FRAME      = 0x0020,
+    CAMERA_MSG_POSTVIEW_FRAME   = 0x0040,
+    CAMERA_MSG_RAW_IMAGE        = 0x0080,
+    CAMERA_MSG_COMPRESSED_IMAGE = 0x0100,
+    CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x0200,
+    CAMERA_MSG_ALL_MSGS         = 0xFFFF
 };
 
 // cmdType in sendCommand functions
@@ -207,7 +208,7 @@
             status_t    cancelAutoFocus();
 
             // take a picture - picture returned from callback
-            status_t    takePicture();
+            status_t    takePicture(int msgType);
 
             // set preview/capture parameters - key/value pairs
             status_t    setParameters(const String8& params);
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index b2310a6..2344b3f 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -70,7 +70,7 @@
     virtual status_t        startRecording() = 0;
 
     // stop recording mode
-    virtual void            stopRecording() = 0;    
+    virtual void            stopRecording() = 0;
 
     // get recording state
     virtual bool            recordingEnabled() = 0;
@@ -84,8 +84,14 @@
     // cancel auto focus
     virtual status_t        cancelAutoFocus() = 0;
 
-    // take a picture
-    virtual status_t        takePicture() = 0;
+    /*
+     * take a picture.
+     * @param msgType the message type an application selectively turn on/off
+     * on a photo-by-photo basis. The supported message types are:
+     * CAMERA_MSG_SHUTTER, CAMERA_MSG_RAW_IMAGE, CAMERA_MSG_COMPRESSED_IMAGE,
+     * and CAMERA_MSG_POSTVIEW_FRAME. Any other message types will be ignored.
+     */
+    virtual status_t        takePicture(int msgType) = 0;
 
     // set preview/capture parameters - key/value pairs
     virtual status_t        setParameters(const String8& params) = 0;
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 0bfb166..cce9129 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -54,6 +54,22 @@
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IOMX>            getOMX() = 0;
+
+    // codecs usage tracking for the battery app
+    enum BatteryDataBits {
+        // tracking audio codec
+        kBatteryDataTrackAudio          = 1,
+        // tracking video codec
+        kBatteryDataTrackVideo          = 2,
+        // codec is started, otherwise codec is paused
+        kBatteryDataCodecStarted        = 4,
+        // tracking decoder (for media player),
+        // otherwise tracking encoder (for media recorder)
+        kBatteryDataTrackDecoder        = 8,
+    };
+
+    virtual void addBatteryData(uint32_t params) = 0;
+    virtual status_t pullBatteryData(Parcel* reply) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 907f119..e288312 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -301,12 +301,12 @@
 }
 
 // take a picture
-status_t Camera::takePicture()
+status_t Camera::takePicture(int msgType)
 {
-    LOGV("takePicture");
+    LOGV("takePicture: 0x%x", msgType);
     sp <ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
-    return c->takePicture();
+    return c->takePicture(msgType);
 }
 
 // set preview/capture parameters - key/value pairs
diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp
index 0881d65..931b57d 100644
--- a/libs/camera/ICamera.cpp
+++ b/libs/camera/ICamera.cpp
@@ -223,11 +223,12 @@
     }
 
     // take a picture - returns an IMemory (ref-counted mmap)
-    status_t takePicture()
+    status_t takePicture(int msgType)
     {
-        LOGV("takePicture");
+        LOGV("takePicture: 0x%x", msgType);
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        data.writeInt32(msgType);
         remote()->transact(TAKE_PICTURE, data, &reply);
         status_t ret = reply.readInt32();
         return ret;
@@ -401,7 +402,8 @@
         case TAKE_PICTURE: {
             LOGV("TAKE_PICTURE");
             CHECK_INTERFACE(ICamera, data, reply);
-            reply->writeInt32(takePicture());
+            int msgType = data.readInt32();
+            reply->writeInt32(takePicture(msgType));
             return NO_ERROR;
         } break;
         case SET_PARAMETERS: {
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index ee2c1e8..a027bc6 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -141,7 +141,9 @@
 
     private static boolean isWMAEnabled() {
         List<AudioDecoder> decoders = DecoderCapabilities.getAudioDecoders();
-        for (AudioDecoder decoder: decoders) {
+        int count = decoders.size();
+        for (int i = 0; i < count; i++) {
+            AudioDecoder decoder = decoders.get(i);
             if (decoder == AudioDecoder.AUDIO_DECODER_WMA) {
                 return true;
             }
@@ -149,6 +151,18 @@
         return false;
     }
 
+    private static boolean isWMVEnabled() {
+        List<VideoDecoder> decoders = DecoderCapabilities.getVideoDecoders();
+        int count = decoders.size();
+        for (int i = 0; i < count; i++) {
+            VideoDecoder decoder = decoders.get(i);
+            if (decoder == VideoDecoder.VIDEO_DECODER_WMV) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     static {
         addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg", MtpConstants.FORMAT_MP3);
         addFileType("M4A", FILE_TYPE_M4A, "audio/mp4", MtpConstants.FORMAT_MPEG);
@@ -184,8 +198,10 @@
         addFileType("WEBM", FILE_TYPE_MKV, "video/x-matroska");
         addFileType("TS", FILE_TYPE_MP2TS, "video/mp2ts");
 
-        addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv", MtpConstants.FORMAT_WMV);
-        addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf");
+        if (isWMVEnabled()) {
+            addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv", MtpConstants.FORMAT_WMV);
+            addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf");
+        }
 
         addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg", MtpConstants.FORMAT_EXIF_JPEG);
         addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg", MtpConstants.FORMAT_EXIF_JPEG);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index f61ac0f..9c92ace 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1055,7 +1055,14 @@
     /**
      * Releases resources associated with this MediaPlayer object.
      * It is considered good practice to call this method when you're
-     * done using the MediaPlayer.
+     * done using the MediaPlayer. For instance, whenever the Activity
+     * of an application is paused, this method should be invoked to
+     * release the MediaPlayer object. In addition to unnecessary resources
+     * (such as memory and instances of codecs) being hold, failure to
+     * call this method immediately if a MediaPlayer object is no longer
+     * needed may also lead to continuous battery consumption for mobile
+     * devices, and playback failure if no multiple instances of the
+     * same codec is supported on a device.
      */
     public void release() {
         stayAwake(false);
@@ -1228,6 +1235,14 @@
     private native final void native_setup(Object mediaplayer_this);
     private native final void native_finalize();
 
+    /**
+     * @param reply Parcel with audio/video duration info for battery
+                    tracking usage
+     * @return The status code.
+     * {@hide}
+     */
+    public native static int native_pullBatteryData(Parcel reply);
+
     @Override
     protected void finalize() { native_finalize(); }
 
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index ad2bf95..e0df257 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3807,7 +3807,6 @@
         } catch (Throwable e) {
             // Allocating to new size with Fixed count
             try {
-                System.gc();
                 rgb888 = new int[thumbnailSize * MAX_THUMBNAIL_PERMITTED];
                 bitmaps = new Bitmap[MAX_THUMBNAIL_PERMITTED];
                 thumbnailCount = MAX_THUMBNAIL_PERMITTED;
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index 69088ed..4faa83a 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -197,7 +197,6 @@
             fl.close();
         }
         imageBitmap.recycle();
-        System.gc();
     }
 
     /*
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 0884e35..ca54432 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -36,6 +36,8 @@
 #include "android_util_Binder.h"
 #include <binder/Parcel.h>
 #include <surfaceflinger/Surface.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
 
 // ----------------------------------------------------------------------------
 
@@ -723,6 +725,21 @@
     process_media_player_call( env, thiz, mp->attachAuxEffect(effectId), NULL, NULL );
 }
 
+static jint
+android_media_MediaPlayer_pullBatteryData(JNIEnv *env, jobject thiz, jobject java_reply)
+{
+    sp<IBinder> binder = defaultServiceManager()->getService(String16("media.player"));
+    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    if (service.get() == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "cannot get MediaPlayerService");
+        return UNKNOWN_ERROR;
+    }
+
+    Parcel *reply = parcelForJavaObject(env, java_reply);
+
+    return service->pullBatteryData(reply);
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -758,6 +775,7 @@
     {"setAudioSessionId",   "(I)V",                             (void *)android_media_MediaPlayer_set_audio_session_id},
     {"setAuxEffectSendLevel", "(F)V",                           (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
     {"attachAuxEffect",     "(I)V",                             (void *)android_media_MediaPlayer_attachAuxEffect},
+    {"native_pullBatteryData", "(Landroid/os/Parcel;)I",        (void *)android_media_MediaPlayer_pullBatteryData},
 };
 
 static const char* const kClassPathName = "android/media/MediaPlayer";
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 77199e1..17a0362 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -37,7 +37,9 @@
     DECODE_FD,
     CREATE_MEDIA_RECORDER,
     CREATE_METADATA_RETRIEVER,
-    GET_OMX
+    GET_OMX,
+    ADD_BATTERY_DATA,
+    PULL_BATTERY_DATA
 };
 
 class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -156,6 +158,19 @@
         remote()->transact(GET_OMX, data, &reply);
         return interface_cast<IOMX>(reply.readStrongBinder());
     }
+
+    virtual void addBatteryData(uint32_t params) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeInt32(params);
+        remote()->transact(ADD_BATTERY_DATA, data, &reply);
+    }
+
+    virtual status_t pullBatteryData(Parcel* reply) {
+        Parcel data;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        return remote()->transact(PULL_BATTERY_DATA, data, reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
@@ -270,6 +285,17 @@
             reply->writeStrongBinder(omx->asBinder());
             return NO_ERROR;
         } break;
+        case ADD_BATTERY_DATA: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            uint32_t params = data.readInt32();
+            addBatteryData(params);
+            return NO_ERROR;
+        } break;
+        case PULL_BATTERY_DATA: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            pullBatteryData(reply);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 60bdd62..8c6f76b 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -23,6 +23,7 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <dirent.h>
 #include <unistd.h>
 
@@ -51,6 +52,8 @@
 #include <media/Metadata.h>
 #include <media/AudioTrack.h>
 
+#include <private/android_filesystem_config.h>
+
 #include "MediaRecorderClient.h"
 #include "MediaPlayerService.h"
 #include "MetadataRetrieverClient.h"
@@ -1762,4 +1765,93 @@
     return 0;
 }
 
+void MediaPlayerService::addBatteryData(uint32_t params)
+{
+    Mutex::Autolock lock(mLock);
+    int uid = IPCThreadState::self()->getCallingUid();
+    if (uid == AID_MEDIA) {
+        return;
+    }
+    int index = mBatteryData.indexOfKey(uid);
+    int32_t time = systemTime() / 1000000L;
+
+    if (index < 0) { // create a new entry for this UID
+        BatteryUsageInfo info;
+        info.audioTotalTime = 0;
+        info.videoTotalTime = 0;
+        info.audioLastTime = 0;
+        info.videoLastTime = 0;
+        info.refCount = 0;
+
+        mBatteryData.add(uid, info);
+    }
+
+    BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
+
+    if (params & kBatteryDataCodecStarted) {
+        if (params & kBatteryDataTrackAudio) {
+            info.audioLastTime -= time;
+            info.refCount ++;
+        }
+        if (params & kBatteryDataTrackVideo) {
+            info.videoLastTime -= time;
+            info.refCount ++;
+        }
+    } else {
+        if (info.refCount == 0) {
+            LOGW("Battery track warning: refCount is already 0");
+            return;
+        } else if (info.refCount < 0) {
+            LOGE("Battery track error: refCount < 0");
+            mBatteryData.removeItem(uid);
+            return;
+        }
+
+        if (params & kBatteryDataTrackAudio) {
+            info.audioLastTime += time;
+            info.refCount --;
+        }
+        if (params & kBatteryDataTrackVideo) {
+            info.videoLastTime += time;
+            info.refCount --;
+        }
+
+        // no stream is being played by this UID
+        if (info.refCount == 0) {
+            info.audioTotalTime += info.audioLastTime;
+            info.audioLastTime = 0;
+            info.videoTotalTime += info.videoLastTime;
+            info.videoLastTime = 0;
+        }
+    }
+}
+
+status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
+    Mutex::Autolock lock(mLock);
+    BatteryUsageInfo info;
+    int size = mBatteryData.size();
+
+    reply->writeInt32(size);
+    int i = 0;
+
+    while (i < size) {
+        info = mBatteryData.valueAt(i);
+
+        reply->writeInt32(mBatteryData.keyAt(i)); //UID
+        reply->writeInt32(info.audioTotalTime);
+        reply->writeInt32(info.videoTotalTime);
+
+        info.audioTotalTime = 0;
+        info.videoTotalTime = 0;
+
+        // remove the UID entry where no stream is being played
+        if (info.refCount <= 0) {
+            mBatteryData.removeItemsAt(i);
+            size --;
+            i --;
+        }
+        i++;
+    }
+    return NO_ERROR;
+}
 } // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 62f8ed6..9f41db0 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -204,7 +204,31 @@
 
             void                removeClient(wp<Client> client);
 
+    // For battery usage tracking purpose
+    struct BatteryUsageInfo {
+        // how many streams are being played by one UID
+        int     refCount;
+        // a temp variable to store the duration(ms) of audio codecs
+        // when we start a audio codec, we minus the system time from audioLastTime
+        // when we pause it, we add the system time back to the audioLastTime
+        // so after the pause, audioLastTime = pause time - start time
+        // if multiple audio streams are played (or recorded), then audioLastTime
+        // = the total playing time of all the streams
+        int32_t audioLastTime;
+        // when all the audio streams are being paused, we assign audioLastTime to
+        // this variable, so this value could be provided to the battery app
+        // in the next pullBatteryData call
+        int32_t audioTotalTime;
 
+        int32_t videoLastTime;
+        int32_t videoTotalTime;
+    };
+    KeyedVector<int, BatteryUsageInfo>    mBatteryData;
+
+    // Collect info of the codec usage from media player and media recorder
+    virtual void                addBatteryData(uint32_t params);
+    // API for the Battery app to pull the data of codecs usage
+    virtual status_t            pullBatteryData(Parcel* reply);
 private:
 
     class Client : public BnMediaPlayer {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 87fdbf2..e3dfabb 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -20,6 +20,10 @@
 
 #include "StagefrightRecorder.h"
 
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <media/IMediaPlayerService.h>
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/CameraSource.h>
@@ -46,9 +50,23 @@
 
 namespace android {
 
+// To collect the encoder usage for the battery app
+static void addBatteryData(uint32_t params) {
+    sp<IBinder> binder =
+        defaultServiceManager()->getService(String16("media.player"));
+    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    CHECK(service.get() != NULL);
+
+    service->addBatteryData(params);
+}
+
+
 StagefrightRecorder::StagefrightRecorder()
     : mWriter(NULL), mWriterAux(NULL),
-      mOutputFd(-1), mOutputFdAux(-1) {
+      mOutputFd(-1), mOutputFdAux(-1),
+      mAudioSource(AUDIO_SOURCE_LIST_END),
+      mVideoSource(VIDEO_SOURCE_LIST_END),
+      mStarted(false) {
 
     LOGV("Constructor");
     reset();
@@ -745,30 +763,54 @@
         return UNKNOWN_ERROR;
     }
 
+    status_t status = OK;
+
     switch (mOutputFormat) {
         case OUTPUT_FORMAT_DEFAULT:
         case OUTPUT_FORMAT_THREE_GPP:
         case OUTPUT_FORMAT_MPEG_4:
-            return startMPEG4Recording();
+            status = startMPEG4Recording();
+            break;
 
         case OUTPUT_FORMAT_AMR_NB:
         case OUTPUT_FORMAT_AMR_WB:
-            return startAMRRecording();
+            status = startAMRRecording();
+            break;
 
         case OUTPUT_FORMAT_AAC_ADIF:
         case OUTPUT_FORMAT_AAC_ADTS:
-            return startAACRecording();
+            status = startAACRecording();
+            break;
 
         case OUTPUT_FORMAT_RTP_AVP:
-            return startRTPRecording();
+            status = startRTPRecording();
+            break;
 
         case OUTPUT_FORMAT_MPEG2TS:
-            return startMPEG2TSRecording();
+            status = startMPEG2TSRecording();
+            break;
 
         default:
             LOGE("Unsupported output file format: %d", mOutputFormat);
-            return UNKNOWN_ERROR;
+            status = UNKNOWN_ERROR;
+            break;
     }
+
+    if ((status == OK) && (!mStarted)) {
+        mStarted = true;
+
+        uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
+        if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+            params |= IMediaPlayerService::kBatteryDataTrackAudio;
+        }
+        if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+            params |= IMediaPlayerService::kBatteryDataTrackVideo;
+        }
+
+        addBatteryData(params);
+    }
+
+    return status;
 }
 
 sp<MediaSource> StagefrightRecorder::createAudioSource() {
@@ -1458,6 +1500,21 @@
         mWriterAux->pause();
     }
 
+    if (mStarted) {
+        mStarted = false;
+
+        uint32_t params = 0;
+        if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+            params |= IMediaPlayerService::kBatteryDataTrackAudio;
+        }
+        if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+            params |= IMediaPlayerService::kBatteryDataTrackVideo;
+        }
+
+        addBatteryData(params);
+    }
+
+
     return OK;
 }
 
@@ -1494,6 +1551,21 @@
         }
     }
 
+    if (mStarted) {
+        mStarted = false;
+
+        uint32_t params = 0;
+        if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+            params |= IMediaPlayerService::kBatteryDataTrackAudio;
+        }
+        if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+            params |= IMediaPlayerService::kBatteryDataTrackVideo;
+        }
+
+        addBatteryData(params);
+    }
+
+
     return err;
 }
 
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 72225db..2c440c1 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -107,6 +107,8 @@
     bool mIsMetaDataStoredInVideoBuffers;
     MediaProfiles *mEncoderProfiles;
 
+    bool mStarted;
+
     status_t setupMPEG4Recording(
         bool useSplitCameraSource,
         int outputFd,
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b1d3630..1b63ab2 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -28,6 +28,8 @@
 #include "include/MPEG2TSExtractor.h"
 
 #include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/AudioPlayer.h>
@@ -155,8 +157,17 @@
             const AwesomeNativeWindowRenderer &);
 };
 
-////////////////////////////////////////////////////////////////////////////////
+// To collect the decoder usage
+void addBatteryData(uint32_t params) {
+    sp<IBinder> binder =
+        defaultServiceManager()->getService(String16("media.player"));
+    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    CHECK(service.get() != NULL);
 
+    service->addBatteryData(params);
+}
+
+////////////////////////////////////////////////////////////////////////////////
 AwesomePlayer::AwesomePlayer()
     : mQueueStarted(false),
       mTimeSource(NULL),
@@ -379,6 +390,17 @@
             mDrmManagerClient = NULL;
     }
 
+    if (mFlags & PLAYING) {
+        uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
+        if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+            params |= IMediaPlayerService::kBatteryDataTrackAudio;
+        }
+        if (mVideoSource != NULL) {
+            params |= IMediaPlayerService::kBatteryDataTrackVideo;
+        }
+        addBatteryData(params);
+    }
+
     if (mFlags & PREPARING) {
         mFlags |= PREPARE_CANCELLED;
         if (mConnectingDataSource != NULL) {
@@ -779,6 +801,16 @@
         seekTo_l(0);
     }
 
+    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
+        | IMediaPlayerService::kBatteryDataTrackDecoder;
+    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+        params |= IMediaPlayerService::kBatteryDataTrackAudio;
+    }
+    if (mVideoSource != NULL) {
+        params |= IMediaPlayerService::kBatteryDataTrackVideo;
+    }
+    addBatteryData(params);
+
     return OK;
 }
 
@@ -933,6 +965,16 @@
                 Playback::PAUSE, 0);
     }
 
+    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
+    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+        params |= IMediaPlayerService::kBatteryDataTrackAudio;
+    }
+    if (mVideoSource != NULL) {
+        params |= IMediaPlayerService::kBatteryDataTrackVideo;
+    }
+
+    addBatteryData(params);
+
     return OK;
 }
 
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index e6fe618..3689557 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -277,7 +277,7 @@
         // this thread as read() will make a copy of this last frame and keep
         // returning it in the quick stop mode.
         Mutex::Autolock autoLock(mQuickStopLock);
-        CHECK_EQ(OK, mCamera->takePicture());
+        CHECK_EQ(OK, mCamera->takePicture(CAMERA_MSG_RAW_IMAGE));
         if (mQuickStop) {
             LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true");
             return;
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..1aea612
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..425535e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..fcad363
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..4ff7db3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..2c4a07f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
new file mode 100644
index 0000000..879c703
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
new file mode 100644
index 0000000..61a7503
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
new file mode 100644
index 0000000..c5edf2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
new file mode 100644
index 0000000..ddf88be
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
index 78ece9e..c77e61e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
index 31fc1b0..b9f721a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..cff969e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
index 19adb4b..d2d7ab3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
index fd419ea..83ce6d0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
index 94e77ae..abe511f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
index 91328c0..d685af8 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
index 2fee6924..8c697a1 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..9a4b807
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
index d0968aa..eb11d04 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
index 991228b..6e54de0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
index ae03e38..5bfb33b 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
index 97b011e..119067b 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
index a826866..a70cc2e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..ea3dba7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
index f6a6891..53221b9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
index 19b9816..11d44d0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
index f8c0961..9defd79 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
index 22deb70..136576d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
index c7c1b49..26ca31f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..de8c5ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
index d9a0702..64dbf3c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
index 6beed8a..34923fb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
index e4179c1..506b5c6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
index 4b2f86d..163976f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
index 6779604..a6af649 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..0c08e52
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
index 1309a97..1d02edb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
index 2fc1e8e..edc9536 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
index 0eef2c1..8376817 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
index f8904e2..ecef547 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
index 3ef306e..a7c48b6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
new file mode 100644
index 0000000..f4bcd9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
index 2ff6d90..b46bb3a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
index 8ff49b0..e8b70f2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
index f416203..4e23c4e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
new file mode 100644
index 0000000..ced9175
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
index 24b7daa..92d4a19 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
index 5ea9142..a208736 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
new file mode 100644
index 0000000..f407bc9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
index 002bf46..b8a65c2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
index 924b84f..a978b68 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
index bd0d1ca..710dd52 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
index f583eec..a7b35e4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
new file mode 100644
index 0000000..bb05449
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
index 66940eaf..a144222 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
index 0381f52..b0eafb6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
index 0b84fe8..f6b83d0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index afb73a9..60fb61d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -668,7 +668,7 @@
     }
 
     public void updateNotification(IBinder key, StatusBarNotification notification) {
-        if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ") // TODO");
+        if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
 
         final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
         if (oldEntry == null) {
@@ -685,7 +685,8 @@
             Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
                     + " ongoing=" + oldNotification.isOngoing()
                     + " expanded=" + oldEntry.expanded
-                    + " contentView=" + oldContentView);
+                    + " contentView=" + oldContentView
+                    + " rowParent=" + oldEntry.row.getParent());
             Slog.d(TAG, "new notification: when=" + notification.notification.when
                     + " ongoing=" + oldNotification.isOngoing()
                     + " contentView=" + contentView);
@@ -806,16 +807,17 @@
             }
         }
         if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
-            if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
-                Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
-                mTicker.halt();
-            } else {
-                Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no");
-            }
-            // refresh icons to show either notifications or the DND message
             mNotificationDNDMode = Prefs.read(mContext)
                         .getBoolean(Prefs.DO_NOT_DISTURB_PREF, Prefs.DO_NOT_DISTURB_DEFAULT);
-            Slog.d(TAG, "DND: " + mNotificationDNDMode);
+
+            if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+                Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes" + (mNotificationDNDMode?" (DND)":""));
+                mTicker.halt();
+            } else {
+                Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no" + (mNotificationDNDMode?" (DND)":""));
+            }
+
+            // refresh icons to show either notifications or the DND message
             reloadAllNotificationIcons();
         } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
             if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
@@ -1241,29 +1243,34 @@
 
         if (mIconLayout == null) return;
 
+        // first, populate the main notification panel
+        loadNotificationPanel();
+
         final LinearLayout.LayoutParams params
             = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
 
         // alternate behavior in DND mode
-        if (mNotificationDNDMode && mIconLayout.getChildCount() == 0) {
-            final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd");
-            iconView.setImageResource(R.drawable.ic_notification_dnd);
-            iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-            iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
+        if (mNotificationDNDMode) {
+            if (mIconLayout.getChildCount() == 0) {
+                final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd");
+                iconView.setImageResource(R.drawable.ic_notification_dnd);
+                iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+                iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
 
-            final Notification dndNotification = new Notification.Builder(mContext)
-                .setContentTitle(mContext.getText(R.string.notifications_off_title))
-                .setContentText(mContext.getText(R.string.notifications_off_text))
-                .setSmallIcon(R.drawable.ic_notification_dnd)
-                .setOngoing(true)
-                .getNotification();
+                final Notification dndNotification = new Notification.Builder(mContext)
+                    .setContentTitle(mContext.getText(R.string.notifications_off_title))
+                    .setContentText(mContext.getText(R.string.notifications_off_text))
+                    .setSmallIcon(R.drawable.ic_notification_dnd)
+                    .setOngoing(true)
+                    .getNotification();
 
-            mNotificationDNDDummyEntry = new NotificationData.Entry(
-                    null,
-                    new StatusBarNotification("", 0, "", 0, 0, dndNotification),
-                    iconView);
+                mNotificationDNDDummyEntry = new NotificationData.Entry(
+                        null,
+                        new StatusBarNotification("", 0, "", 0, 0, dndNotification),
+                        iconView);
 
-            mIconLayout.addView(iconView, params);
+                mIconLayout.addView(iconView, params);
+            }
 
             return;
         }
@@ -1305,8 +1312,6 @@
                 mIconLayout.addView(v, i, params);
             }
         }
-
-        loadNotificationPanel();
     }
 
     private void loadNotificationPanel() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 9794944..f6649fd 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2570,6 +2570,16 @@
     }
 
     private int getCurrentLandscapeRotation(int lastRotation) {
+        // if the user has locked rotation, we ignore the sensor 
+        if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
+            if (isLandscapeOrSeascape(mUserRotation)) {
+                return mUserRotation;
+            } else {
+                // it seems odd to obey the sensor at all if rotation lock is enabled
+                return mLandscapeRotation;
+            }
+        }
+
         int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
         if (isLandscapeOrSeascape(sensorRotation)) {
             return sensorRotation;
@@ -2587,6 +2597,16 @@
     }
 
     private int getCurrentPortraitRotation(int lastRotation) {
+        // if the user has locked rotation, we ignore the sensor 
+        if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
+            if (isAnyPortrait(mUserRotation)) {
+                return mUserRotation;
+            } else {
+                // it seems odd to obey the sensor at all if rotation lock is enabled
+                return mPortraitRotation;
+            }
+        }
+
         int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
         if (isAnyPortrait(sensorRotation)) {
             return sensorRotation;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 3d8ca7a..a09e16b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -727,17 +727,30 @@
 }
 
 // take a picture - image is returned in callback
-status_t CameraService::Client::takePicture() {
-    LOG1("takePicture (pid %d)", getCallingPid());
+status_t CameraService::Client::takePicture(int msgType) {
+    LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
 
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
 
-    enableMsgType(CAMERA_MSG_SHUTTER |
-                  CAMERA_MSG_POSTVIEW_FRAME |
-                  CAMERA_MSG_RAW_IMAGE |
-                  CAMERA_MSG_COMPRESSED_IMAGE);
+    if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
+        (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
+        LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
+                " cannot be both enabled");
+        return BAD_VALUE;
+    }
+
+    // We only accept picture related message types
+    // and ignore other types of messages for takePicture().
+    int picMsgType = msgType
+                        & (CAMERA_MSG_SHUTTER |
+                           CAMERA_MSG_POSTVIEW_FRAME |
+                           CAMERA_MSG_RAW_IMAGE |
+                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
+                           CAMERA_MSG_COMPRESSED_IMAGE);
+
+    enableMsgType(picMsgType);
 
     return mHardware->takePicture();
 }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ccb9cf7..1c43b00 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -108,7 +108,7 @@
         virtual void            releaseRecordingFrame(const sp<IMemory>& mem);
         virtual status_t        autoFocus();
         virtual status_t        cancelAutoFocus();
-        virtual status_t        takePicture();
+        virtual status_t        takePicture(int msgType);
         virtual status_t        setParameters(const String8& params);
         virtual String8         getParameters() const;
         virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index cc25e8d..f9b94a3 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -96,6 +96,9 @@
     private boolean mDeviceIdle;
     private int mPluggedType;
 
+    /* Chipset supports background scan */
+    private final boolean mBackgroundScanSupported;
+
     // true if the user enabled Wifi while in airplane mode
     private AtomicBoolean mAirplaneModeOverwridden = new AtomicBoolean(false);
 
@@ -369,6 +372,9 @@
                 Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
         mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(new Handler());
         mNotificationEnabledSettingObserver.register();
+
+        mBackgroundScanSupported = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_wifi_background_scan_support);
     }
 
     /**
@@ -900,6 +906,9 @@
                 reportStartWorkSource();
                 evaluateTrafficStatsPolling();
                 mWifiStateMachine.enableRssiPolling(true);
+                if (mBackgroundScanSupported) {
+                    mWifiStateMachine.enableBackgroundScan(false);
+                }
                 mWifiStateMachine.enableAllNetworks();
                 updateWifiState();
             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
@@ -909,6 +918,9 @@
                 mScreenOff = true;
                 evaluateTrafficStatsPolling();
                 mWifiStateMachine.enableRssiPolling(false);
+                if (mBackgroundScanSupported) {
+                    mWifiStateMachine.enableBackgroundScan(true);
+                }
                 /*
                  * Set a timer to put Wi-Fi to sleep, but only if the screen is off
                  * AND the "stay on while plugged in" setting doesn't match the
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0f7d639..57af001 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -341,6 +341,45 @@
     drawWithOpenGL(clip, tex);
 }
 
+// As documented in libhardware header, formats in the range
+// 0x100 - 0x1FF are specific to the HAL implementation, and
+// are known to have no alpha channel
+// TODO: move definition for device-specific range into
+// hardware.h, instead of using hard-coded values here.
+#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
+
+bool Layer::needsBlending(const sp<GraphicBuffer>& buffer) const
+{
+    // If buffers where set with eOpaque flag, all buffers are known to
+    // be opaque without having to check their actual format
+    if (mNeedsBlending && buffer != NULL) {
+        PixelFormat format = buffer->getPixelFormat();
+
+        if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+            return false;
+        }
+
+        PixelFormatInfo info;
+        status_t err = getPixelFormatInfo(format, &info);
+        if (!err && info.h_alpha <= info.l_alpha) {
+            return false;
+        }
+    }
+
+    // Return opacity as determined from flags and format options
+    // passed to setBuffers()
+    return mNeedsBlending;
+}
+
+bool Layer::needsBlending() const
+{
+    if (mBufferManager.hasActiveBuffer()) {
+        return needsBlending(mBufferManager.getActiveBuffer());
+    }
+
+    return mNeedsBlending;
+}
+
 bool Layer::needsFiltering() const
 {
     if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
@@ -588,6 +627,9 @@
     // we retired a buffer, which becomes the new front buffer
 
     const bool noActiveBuffer = !mBufferManager.hasActiveBuffer();
+    const bool activeBlending =
+            noActiveBuffer ? true : needsBlending(mBufferManager.getActiveBuffer());
+
     if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
         LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
         mPostedDirtyRegion.clear();
@@ -602,6 +644,12 @@
 
     sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
     if (newFrontBuffer != NULL) {
+        if (!noActiveBuffer && activeBlending != needsBlending(newFrontBuffer)) {
+            // new buffer has different opacity than previous active buffer, need
+            // to recompute visible regions accordingly
+            recomputeVisibleRegions = true;
+        }
+
         // get the dirty region
         // compute the posted region
         const Region dirty(lcblk->getDirtyRegion(buf));
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2b38414..bccc900 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -75,7 +75,8 @@
     virtual uint32_t doTransaction(uint32_t transactionFlags);
     virtual void lockPageFlip(bool& recomputeVisibleRegions);
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
-    virtual bool needsBlending() const      { return mNeedsBlending; }
+    virtual bool needsBlending(const sp<GraphicBuffer>& buffer) const;
+    virtual bool needsBlending() const;
     virtual bool needsDithering() const     { return mNeedsDithering; }
     virtual bool needsFiltering() const;
     virtual bool isSecure() const           { return mSecure; }
diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
index 5211b0a..d3c492e 100644
--- a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
@@ -9,5 +9,7 @@
 			android:layout_width="wrap_content"/>
 	<ImageView
 			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"/>
+			android:layout_width="wrap_content"
+			android:layout_marginLeft="3dip"
+			android:layout_marginRight="5dip"/>
 </merge>
diff --git a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
index e193477..a50a2bd 100644
--- a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
@@ -63,7 +63,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate(int opColor, int tolerance, int nativeMode) {
         AvoidXfermode_Delegate newDelegate = new AvoidXfermode_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
index c6fde7b..9a8cf04 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
@@ -76,7 +76,7 @@
                 bitmap.getImage(),
                 Shader_Delegate.getTileMode(shaderTileModeX),
                 Shader_Delegate.getTileMode(shaderTileModeY));
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 0c87766..b6d5725 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -245,12 +245,12 @@
 
     @LayoutlibDelegate
     /*package*/ static void nativeDestructor(int nativeBitmap) {
-        sManager.removeDelegate(nativeBitmap);
+        sManager.removeJavaReferenceFor(nativeBitmap);
     }
 
     @LayoutlibDelegate
     /*package*/ static void nativeRecycle(int nativeBitmap) {
-        sManager.removeDelegate(nativeBitmap);
+        sManager.removeJavaReferenceFor(nativeBitmap);
     }
 
     @LayoutlibDelegate
@@ -522,7 +522,7 @@
 
     private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
         // get its native_int
-        int nativeInt = sManager.addDelegate(delegate);
+        int nativeInt = sManager.addNewDelegate(delegate);
 
         // and create/return a new Bitmap with it
         return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density);
diff --git a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
index 92d0d0a..4becba1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
@@ -57,7 +57,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeConstructor(float radius, int style) {
         BlurMaskFilter_Delegate newDelegate = new BlurMaskFilter_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index e8a99b5..f0e727f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -64,7 +64,7 @@
     private Bitmap_Delegate mBitmap;
     private GcSnapshot mSnapshot;
 
-    private int mDrawFilter = 0;
+    private DrawFilter_Delegate mDrawFilter = null;
 
     // ---- Public Helper methods ----
 
@@ -95,7 +95,7 @@
      * @return the delegate or null.
      */
     public DrawFilter_Delegate getDrawFilter() {
-        return DrawFilter_Delegate.getDelegate(mDrawFilter);
+        return mDrawFilter;
     }
 
     // ---- native methods ----
@@ -313,12 +313,12 @@
             // create a new Canvas_Delegate with the given bitmap and return its new native int.
             Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);
 
-            return sManager.addDelegate(newDelegate);
+            return sManager.addNewDelegate(newDelegate);
         } else {
             // create a new Canvas_Delegate and return its new native int.
             Canvas_Delegate newDelegate = new Canvas_Delegate();
 
-            return sManager.addDelegate(newDelegate);
+            return sManager.addNewDelegate(newDelegate);
         }
     }
 
@@ -510,26 +510,18 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeSetDrawFilter(int nativeCanvas,
-                                                   int nativeFilter) {
+    /*package*/ static void nativeSetDrawFilter(int nativeCanvas, int nativeFilter) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
             return;
         }
 
-        canvasDelegate.mDrawFilter = nativeFilter;
+        canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);
 
-        // get the delegate only because we don't support them at all for the moment, so
-        // we can display the message now.
-
-        DrawFilter_Delegate filterDelegate = DrawFilter_Delegate.getDelegate(nativeFilter);
-        if (canvasDelegate == null) {
-            return;
-        }
-
-        if (filterDelegate.isSupported() == false) {
+        if (canvasDelegate.mDrawFilter != null &&
+                canvasDelegate.mDrawFilter.isSupported() == false) {
             Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
-                    filterDelegate.getSupportMessage(), null, null /*data*/);
+                    canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
         }
     }
 
@@ -956,7 +948,7 @@
         draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
                 new GcSnapshot.Drawable() {
             public void draw(Graphics2D graphics, Paint_Delegate paint) {
-                // WARNING: the logic in this method is similar to Paint.measureText.
+                // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
                 // Any change to this method should be reflected in Paint.measureText
                 // Paint.TextAlign indicates how the text is positioned relative to X.
                 // LEFT is the default and there's nothing to do.
@@ -1139,7 +1131,7 @@
         canvasDelegate.dispose();
 
         // remove it from the manager.
-        sManager.removeDelegate(nativeCanvas);
+        sManager.removeJavaReferenceFor(nativeCanvas);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
index 789c6e6..e786eb5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
@@ -57,7 +57,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void finalizer(int native_instance, int nativeColorFilter) {
-        sManager.removeDelegate(native_instance);
+        sManager.removeJavaReferenceFor(native_instance);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
index 462b1e6..2de344b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
@@ -57,7 +57,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeColorMatrixFilter(float[] array) {
         ColorMatrixColorFilter_Delegate newDelegate = new ColorMatrixColorFilter_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
index 2bdaa5b..7c04a87 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
@@ -64,7 +64,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate(int outerpe, int innerpe) {
         ComposePathEffect_Delegate newDelegate = new ComposePathEffect_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
index a2ecb8f..f6e1d00 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
@@ -67,7 +67,7 @@
             int native_mode) {
         // FIXME not supported yet.
         ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -75,7 +75,7 @@
             int porterDuffMode) {
         // FIXME not supported yet.
         ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
index c677de8..b0f8168 100644
--- a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
@@ -64,7 +64,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate(float radius) {
         CornerPathEffect_Delegate newDelegate = new CornerPathEffect_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
index 12a4d4a..d97c2ec 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
@@ -75,7 +75,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate(float intervals[], float phase) {
         DashPathEffect_Delegate newDelegate = new DashPathEffect_Delegate(intervals, phase);
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
index ac69712..ec4a810 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
@@ -64,7 +64,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate(float length, float deviation) {
         DiscretePathEffect_Delegate newDelegate = new DiscretePathEffect_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
index a98f0a9..37c7359 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
@@ -57,7 +57,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void nativeDestructor(int nativeDrawFilter) {
-        sManager.removeDelegate(nativeDrawFilter);
+        sManager.removeJavaReferenceFor(nativeDrawFilter);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
index 31f8bbf..ebc1c1d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
@@ -58,7 +58,7 @@
     /*package*/ static int nativeConstructor(float[] direction, float ambient,
             float specular, float blurRadius) {
         EmbossMaskFilter_Delegate newDelegate = new EmbossMaskFilter_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
index fcb62a8..51e0576 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
@@ -57,7 +57,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeConstructor() {
         LayerRasterizer_Delegate newDelegate = new LayerRasterizer_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
index b272534..0ee883d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
@@ -57,7 +57,7 @@
     @LayoutlibDelegate
     /*package*/ static int native_CreateLightingFilter(int mul, int add) {
         LightingColorFilter_Delegate newDelegate = new LightingColorFilter_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index 8060577..a2ba758 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -59,7 +59,7 @@
             int colors[], float positions[], int tileMode) {
         LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(x0, y0, x1, y1,
                 colors, positions, Shader_Delegate.getTileMode(tileMode));
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
index 4adca27..5a6167d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
@@ -57,7 +57,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void nativeDestructor(int native_filter) {
-        sManager.removeDelegate(native_filter);
+        sManager.removeJavaReferenceFor(native_filter);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 68a476f..251aa16 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -189,7 +189,7 @@
             }
         }
 
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -765,7 +765,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void finalizer(int native_instance) {
-        sManager.removeDelegate(native_instance);
+        sManager.removeJavaReferenceFor(native_instance);
     }
 
     // ---- Private helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
index dfcb591..71d346a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
@@ -57,7 +57,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeConstructor(int clearBits, int setBits) {
         PaintFlagsDrawFilter_Delegate newDelegate = new PaintFlagsDrawFilter_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index f5d2547..51b3efe 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -32,6 +32,7 @@
 import java.awt.Toolkit;
 import java.awt.font.FontRenderContext;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -75,19 +76,19 @@
     private int mCap;
     private int mJoin;
     private int mTextAlign;
-    private int mTypeface;
+    private Typeface_Delegate mTypeface;
     private float mStrokeWidth;
     private float mStrokeMiter;
     private float mTextSize;
     private float mTextScaleX;
     private float mTextSkewX;
 
-    private int mXfermode;
-    private int mColorFilter;
-    private int mShader;
-    private int mPathEffect;
-    private int mMaskFilter;
-    private int mRasterizer;
+    private Xfermode_Delegate mXfermode;
+    private ColorFilter_Delegate mColorFilter;
+    private Shader_Delegate mShader;
+    private PathEffect_Delegate mPathEffect;
+    private MaskFilter_Delegate mMaskFilter;
+    private Rasterizer_Delegate mRasterizer;
 
 
     // ---- Public Helper methods ----
@@ -172,17 +173,16 @@
     }
 
     public Stroke getJavaStroke() {
-        PathEffect_Delegate effectDelegate = PathEffect_Delegate.getDelegate(mPathEffect);
-        if (effectDelegate != null) {
-            if (effectDelegate.isSupported()) {
-                Stroke stroke = effectDelegate.getStroke(this);
+        if (mPathEffect != null) {
+            if (mPathEffect.isSupported()) {
+                Stroke stroke = mPathEffect.getStroke(this);
                 assert stroke != null;
                 if (stroke != null) {
                     return stroke;
                 }
             } else {
                 Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
-                        effectDelegate.getSupportMessage(),
+                        mPathEffect.getSupportMessage(),
                         null, null /*data*/);
             }
         }
@@ -201,7 +201,7 @@
      * @return the delegate or null.
      */
     public Xfermode_Delegate getXfermode() {
-        return  Xfermode_Delegate.getDelegate(mXfermode);
+        return mXfermode;
     }
 
     /**
@@ -210,7 +210,7 @@
      * @return the delegate or null.
      */
     public ColorFilter_Delegate getColorFilter() {
-        return ColorFilter_Delegate.getDelegate(mColorFilter);
+        return mColorFilter;
     }
 
     /**
@@ -219,7 +219,7 @@
      * @return the delegate or null.
      */
     public Shader_Delegate getShader() {
-        return Shader_Delegate.getDelegate(mShader);
+        return mShader;
     }
 
     /**
@@ -228,7 +228,7 @@
      * @return the delegate or null.
      */
     public MaskFilter_Delegate getMaskFilter() {
-        return MaskFilter_Delegate.getDelegate(mMaskFilter);
+        return mMaskFilter;
     }
 
     /**
@@ -237,7 +237,7 @@
      * @return the delegate or null.
      */
     public Rasterizer_Delegate getRasterizer() {
-        return Rasterizer_Delegate.getDelegate(mRasterizer);
+        return mRasterizer;
     }
 
     // ---- native methods ----
@@ -542,9 +542,6 @@
     @LayoutlibDelegate
     /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
             int count) {
-        // WARNING: the logic in this method is similar to Canvas.drawText.
-        // Any change to this method should be reflected in Canvas.drawText
-
         // get the delegate
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
@@ -567,25 +564,57 @@
     @LayoutlibDelegate
     /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
             float maxWidth, float[] measuredWidth) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Paint.native_breakText is not supported.", null, null /*data*/);
-        return 0;
+
+        // get the delegate
+        Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+        if (delegate == null) {
+            return 0;
+        }
+
+        int inc = count > 0 ? 1 : -1;
+
+        int measureIndex = 0;
+        float measureAcc = 0;
+        for (int i = index; i != index + count; i += inc, measureIndex++) {
+            int start, end;
+            if (i < index) {
+                start = i;
+                end = index;
+            } else {
+                start = index;
+                end = i;
+            }
+
+            // measure from start to end
+            float res = delegate.measureText(text, start, end - start + 1);
+
+            if (measuredWidth != null) {
+                measuredWidth[measureIndex] = res;
+            }
+
+            measureAcc += res;
+            if (res > maxWidth) {
+                // we should not return this char index, but since it's 0-based
+                // and we need to return a count, we simply return measureIndex;
+                return measureIndex;
+            }
+
+        }
+
+        return measureIndex;
     }
 
     @LayoutlibDelegate
     /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
             float maxWidth, float[] measuredWidth) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Paint.native_breakText is not supported.", null, null /*data*/);
-        return 0;
+        return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth,
+                measuredWidth);
     }
 
     @LayoutlibDelegate
     /*package*/ static int native_init() {
         Paint_Delegate newDelegate = new Paint_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -597,7 +626,7 @@
         }
 
         Paint_Delegate newDelegate = new Paint_Delegate(delegate);
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -728,7 +757,9 @@
             return shader;
         }
 
-        return delegate.mShader = shader;
+        delegate.mShader = Shader_Delegate.getDelegate(shader);
+
+        return shader;
     }
 
     @LayoutlibDelegate
@@ -739,13 +770,12 @@
             return filter;
         }
 
-        delegate.mColorFilter = filter;
+        delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);;
 
         // since none of those are supported, display a fidelity warning right away
-        ColorFilter_Delegate filterDelegate = delegate.getColorFilter();
-        if (filterDelegate != null && filterDelegate.isSupported() == false) {
+        if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
             Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
-                    filterDelegate.getSupportMessage(), null, null /*data*/);
+                    delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
         }
 
         return filter;
@@ -759,7 +789,9 @@
             return xfermode;
         }
 
-        return delegate.mXfermode = xfermode;
+        delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode);
+
+        return xfermode;
     }
 
     @LayoutlibDelegate
@@ -770,7 +802,9 @@
             return effect;
         }
 
-        return delegate.mPathEffect = effect;
+        delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
+
+        return effect;
     }
 
     @LayoutlibDelegate
@@ -781,13 +815,12 @@
             return maskfilter;
         }
 
-        delegate.mMaskFilter = maskfilter;
+        delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
 
         // since none of those are supported, display a fidelity warning right away
-        MaskFilter_Delegate filterDelegate = delegate.getMaskFilter();
-        if (filterDelegate != null && filterDelegate.isSupported() == false) {
+        if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) {
             Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
-                    filterDelegate.getSupportMessage(), null, null /*data*/);
+                    delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
         }
 
         return maskfilter;
@@ -801,9 +834,9 @@
             return 0;
         }
 
-        delegate.mTypeface = typeface;
+        delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
         delegate.updateFontObject();
-        return delegate.mTypeface;
+        return typeface;
     }
 
     @LayoutlibDelegate
@@ -814,13 +847,12 @@
             return rasterizer;
         }
 
-        delegate.mRasterizer = rasterizer;
+        delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
 
         // since none of those are supported, display a fidelity warning right away
-        Rasterizer_Delegate rasterizerDelegate = delegate.getRasterizer();
-        if (rasterizerDelegate != null && rasterizerDelegate.isSupported() == false) {
+        if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) {
             Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
-                    rasterizerDelegate.getSupportMessage(), null, null /*data*/);
+                    delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
         }
 
         return rasterizer;
@@ -862,19 +894,49 @@
     @LayoutlibDelegate
     /*package*/ static int native_getTextWidths(int native_object, char[] text, int index,
             int count, float[] widths) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Paint.getTextWidths is not supported.", null, null /*data*/);
+        // get the delegate from the native int.
+        Paint_Delegate delegate = sManager.getDelegate(native_object);
+        if (delegate == null) {
+            return 0;
+        }
+
+        if (delegate.mFonts.size() > 0) {
+            // FIXME: handle multi-char characters (see measureText)
+            float totalAdvance = 0;
+            for (int i = 0; i < count; i++) {
+                char c = text[i + index];
+                boolean found = false;
+                for (FontInfo info : delegate.mFonts) {
+                    if (info.mFont.canDisplay(c)) {
+                        float adv = info.mMetrics.charWidth(c);
+                        totalAdvance += adv;
+                        if (widths != null) {
+                            widths[i] = adv;
+                        }
+
+                        found = true;
+                        break;
+                    }
+                }
+
+                if (found == false) {
+                    // no advance for this char.
+                    if (widths != null) {
+                        widths[i] = 0.f;
+                    }
+                }
+            }
+
+            return (int) totalAdvance;
+        }
+
         return 0;
     }
 
     @LayoutlibDelegate
     /*package*/ static int native_getTextWidths(int native_object, String text, int start,
             int end, float[] widths) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Paint.getTextWidths is not supported.", null, null /*data*/);
-        return 0;
+        return native_getTextWidths(native_object, text.toCharArray(), start, end - start, widths);
     }
 
     @LayoutlibDelegate
@@ -971,22 +1033,33 @@
     @LayoutlibDelegate
     /*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start,
             int end, Rect bounds) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Paint.getStringBounds is not supported.", null, null /*data*/);
+        nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bounds);
     }
 
     @LayoutlibDelegate
     /*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index,
             int count, Rect bounds) {
-        // FIXME
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                "Paint.getCharArrayBounds is not supported.", null, null /*data*/);
+
+        // get the delegate from the native int.
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
+        if (delegate == null) {
+            return;
+        }
+
+        // FIXME should test if the main font can display all those characters.
+        // See MeasureText
+        if (delegate.mFonts.size() > 0) {
+            FontInfo mainInfo = delegate.mFonts.get(0);
+
+            Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count,
+                    delegate.mFontContext);
+            bounds.set(0, 0, (int) rect.getWidth(), (int) rect.getHeight());
+        }
     }
 
     @LayoutlibDelegate
     /*package*/ static void finalizer(int nativePaint) {
-        sManager.removeDelegate(nativePaint);
+        sManager.removeJavaReferenceFor(nativePaint);
     }
 
     // ---- Private delegate/helper methods ----
@@ -1028,18 +1101,18 @@
         mCap = Paint.Cap.BUTT.nativeInt;
         mJoin = Paint.Join.MITER.nativeInt;
         mTextAlign = 0;
-        mTypeface = Typeface.sDefaults[0].native_instance;
+        mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
         mStrokeWidth = 1.f;
         mStrokeMiter = 4.f;
         mTextSize = 20.f;
         mTextScaleX = 1.f;
         mTextSkewX = 0.f;
-        mXfermode = 0;
-        mColorFilter = 0;
-        mShader = 0;
-        mPathEffect = 0;
-        mMaskFilter = 0;
-        mRasterizer = 0;
+        mXfermode = null;
+        mColorFilter = null;
+        mShader = null;
+        mPathEffect = null;
+        mMaskFilter = null;
+        mRasterizer = null;
         updateFontObject();
     }
 
@@ -1048,9 +1121,9 @@
      */
     @SuppressWarnings("deprecation")
     private void updateFontObject() {
-        if (mTypeface != 0) {
+        if (mTypeface != null) {
             // Get the fonts from the TypeFace object.
-            List<Font> fonts = Typeface_Delegate.getFonts(mTypeface);
+            List<Font> fonts = mTypeface.getFonts();
 
             // create new font objects as well as FontMetrics, based on the current text size
             // and skew info.
@@ -1073,6 +1146,10 @@
     }
 
     /*package*/ float measureText(char[] text, int index, int count) {
+
+        // WARNING: the logic in this method is similar to Canvas_Delegate.native_drawText
+        // Any change to this method should be reflected there as well
+
         if (mFonts.size() > 0) {
             FontInfo mainFont = mFonts.get(0);
             int i = index;
@@ -1120,6 +1197,8 @@
                     i += size;
                 }
             }
+
+            return total;
         }
 
         return 0;
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
index 98a5386..c448f0e 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
@@ -65,7 +65,7 @@
     /*package*/ static int nativeCreate(int native_path, float advance, float phase,
             int native_style) {
         PathDashPathEffect_Delegate newDelegate = new PathDashPathEffect_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
index bbbebdd..4d5311a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
@@ -61,7 +61,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void nativeDestructor(int native_patheffect) {
-        sManager.removeDelegate(native_patheffect);
+        sManager.removeJavaReferenceFor(native_patheffect);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 9510ce0..c29e9b6 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -90,7 +90,7 @@
         // create the delegate
         Path_Delegate newDelegate = new Path_Delegate();
 
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -104,7 +104,7 @@
             newDelegate.set(pathDelegate);
         }
 
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -440,7 +440,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void finalizer(int nPath) {
-        sManager.removeDelegate(nPath);
+        sManager.removeJavaReferenceFor(nPath);
     }
 
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
index bbb20e9..4ab044b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
@@ -63,7 +63,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate(int opColor) {
         PixelXorXfermode_Delegate newDelegate = new PixelXorXfermode_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
index 33f6c44..c45dbaa 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
@@ -57,7 +57,7 @@
     @LayoutlibDelegate
     /*package*/ static int native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) {
         PorterDuffColorFilter_Delegate newDelegate = new PorterDuffColorFilter_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index 116a773..4301c1a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -129,7 +129,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreateXfermode(int mode) {
         PorterDuffXfermode_Delegate newDelegate = new PorterDuffXfermode_Delegate(mode);
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index 8723ed1..9bf78b4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -58,7 +58,7 @@
             int colors[], float positions[], int tileMode) {
         RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(x, y, radius,
                 colors, positions, Shader_Delegate.getTileMode(tileMode));
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
index 2826278..e388bd9 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
@@ -57,7 +57,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void finalizer(int native_instance) {
-        sManager.removeDelegate(native_instance);
+        sManager.removeJavaReferenceFor(native_instance);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index 7b91215..91f4347 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -266,12 +266,12 @@
     @LayoutlibDelegate
     /*package*/ static int nativeConstructor() {
         Region_Delegate newDelegate = new Region_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
     /*package*/ static void nativeDestructor(int native_region) {
-        sManager.removeDelegate(native_region);
+        sManager.removeJavaReferenceFor(native_region);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index a1b8bdd..a008d15 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -45,7 +45,7 @@
     // ---- delegate helper data ----
 
     // ---- delegate data ----
-    private int mLocalMatrix = 0;
+    private Matrix_Delegate mLocalMatrix = null;
 
     // ---- Public Helper methods ----
 
@@ -77,7 +77,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void nativeDestructor(int native_shader, int native_skiaShader) {
-        sManager.removeDelegate(native_shader);
+        sManager.removeJavaReferenceFor(native_shader);
     }
 
     @LayoutlibDelegate
@@ -89,15 +89,14 @@
             return;
         }
 
-        shaderDelegate.mLocalMatrix = matrix_instance;
+        shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance);
     }
 
     // ---- Private delegate/helper methods ----
 
     protected java.awt.geom.AffineTransform getLocalMatrix() {
-        Matrix_Delegate localMatrixDelegate = Matrix_Delegate.getDelegate(mLocalMatrix);
-        if (localMatrixDelegate != null) {
-            return localMatrixDelegate.getAffineTransform();
+        if (mLocalMatrix != null) {
+            return mLocalMatrix.getAffineTransform();
         }
 
         return new java.awt.geom.AffineTransform();
diff --git a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
index 0c9ee48..410df0c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
@@ -64,7 +64,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate(int first, int second) {
         SumPathEffect_Delegate newDelegate = new SumPathEffect_Delegate();
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 382e34c..966e06e 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -54,7 +54,7 @@
     @LayoutlibDelegate
     /*package*/ static int nativeCreate1(float x, float y, int colors[], float positions[]) {
         SweepGradient_Delegate newDelegate = new SweepGradient_Delegate(x, y, colors, positions);
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 1992341..5af16ae 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -74,6 +74,10 @@
         sPostInitDelegate.clear();
     }
 
+    public static Typeface_Delegate getDelegate(int nativeTypeface) {
+        return sManager.getDelegate(nativeTypeface);
+    }
+
     public static List<Font> getFonts(Typeface typeface) {
         return getFonts(typeface.native_instance);
     }
@@ -84,7 +88,11 @@
             return null;
         }
 
-        return delegate.mFonts;
+        return delegate.getFonts();
+    }
+
+    public List<Font> getFonts() {
+        return mFonts;
     }
 
     // ---- native methods ----
@@ -105,7 +113,7 @@
             sPostInitDelegate.add(newDelegate);
         }
 
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -125,7 +133,7 @@
             sPostInitDelegate.add(newDelegate);
         }
 
-        return sManager.addDelegate(newDelegate);
+        return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
@@ -144,7 +152,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void nativeUnref(int native_instance) {
-        sManager.removeDelegate(native_instance);
+        sManager.removeJavaReferenceFor(native_instance);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
index 88df027..f3401fc 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
@@ -61,7 +61,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void finalizer(int native_instance) {
-        sManager.removeDelegate(native_instance);
+        sManager.removeJavaReferenceFor(native_instance);
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
index 04d06e4..9fab51a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
@@ -30,7 +30,7 @@
 public class PhoneSystemBar extends CustomBar {
 
     public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
-        super(context, density, "/bars/tablet_system_bar.xml");
+        super(context, density, "/bars/phone_system_bar.xml");
 
         setGravity(mGravity | Gravity.RIGHT);
         setBackgroundColor(0xFF000000);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index 05a258d..295c98c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -16,8 +16,14 @@
 
 package com.android.layoutlib.bridge.impl;
 
+import com.android.layoutlib.bridge.util.SparseWeakArray;
+
 import android.util.SparseArray;
 
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Manages native delegates.
  *
@@ -44,13 +50,32 @@
  * will do is call {@link #getDelegate(int)} to get the Java object matching the int.
  *
  * Typical native init methods are returning a new int back to the Java class, so
- * {@link #addDelegate(Object)} does the same.
+ * {@link #addNewDelegate(Object)} does the same.
+ *
+ * The JNI references are counted, so we do the same through a {@link WeakReference}. Because
+ * the Java object needs to count as a reference (even though it only holds an int), we use the
+ * following mechanism:
+ *
+ * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(int)} adds and removes
+ *   the delegate to/from a list. This list hold the reference and prevents the GC from reclaiming
+ *   the delegate.
+ *
+ * - {@link #addNewDelegate(Object)} also adds the delegate to a {@link SparseArray} that holds a
+ *   {@link WeakReference} to the delegate. This allows the delegate to be deleted automatically
+ *   when nothing references it. This means that any class that holds a delegate (except for the
+ *   Java main class) must not use the int but the Delegate class instead. The integers must
+ *   only be used in the API between the main Java class and the Delegate.
  *
  * @param <T> the delegate class to manage
  */
 public final class DelegateManager<T> {
-
-    private final SparseArray<T> mDelegates = new SparseArray<T>();
+    private final SparseWeakArray<T> mDelegates = new SparseWeakArray<T>();
+    /** list used to store delegates when their main object holds a reference to them.
+     * This is to ensure that the WeakReference in the SparseWeakArray doesn't get GC'ed
+     * @see #addNewDelegate(Object)
+     * @see #removeJavaReferenceFor(int)
+     */
+    private final List<T> mJavaReferences = new ArrayList<T>();
     private int mDelegateCounter = 0;
 
     /**
@@ -77,17 +102,20 @@
      * @param newDelegate the delegate to add
      * @return a unique native int to identify the delegate
      */
-    public int addDelegate(T newDelegate) {
+    public int addNewDelegate(T newDelegate) {
         int native_object = ++mDelegateCounter;
         mDelegates.put(native_object, newDelegate);
+        assert !mJavaReferences.contains(newDelegate);
+        mJavaReferences.add(newDelegate);
         return native_object;
     }
 
     /**
-     * Removes the delegate matching the given native int.
-     * @param native_object the native int.
+     * Removes the main reference on the given delegate.
+     * @param native_object the native integer representing the delegate.
      */
-    public void removeDelegate(int native_object) {
-        mDelegates.remove(native_object);
+    public void removeJavaReferenceFor(int native_object) {
+        T delegate = getDelegate(native_object);
+        mJavaReferences.remove(delegate);
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
new file mode 100644
index 0000000..22f1609
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2011 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.layoutlib.bridge.util;
+
+
+import com.android.internal.util.ArrayUtils;
+
+import android.util.SparseArray;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * This is a custom {@link SparseArray} that uses {@link WeakReference} around the objects added
+ * to it. When the array is compacted, not only deleted indices but also empty references
+ * are removed, making the array efficient at removing references that were reclaimed.
+ *
+ * The code is taken from {@link SparseArray} directly and adapted to use weak references.
+ *
+ * Because our usage means that we never actually call {@link #remove(int)} or {@link #delete(int)},
+ * we must manually check if there are reclaimed references to trigger an internal compact step
+ * (which is normally only triggered when an item is manually removed).
+ *
+ * SparseArrays map integers to Objects.  Unlike a normal array of Objects,
+ * there can be gaps in the indices.  It is intended to be more efficient
+ * than using a HashMap to map Integers to Objects.
+ */
+@SuppressWarnings("unchecked")
+public class SparseWeakArray<E> {
+
+    private static final Object DELETED_REF = new Object();
+    private static final WeakReference<?> DELETED = new WeakReference(DELETED_REF);
+    private boolean mGarbage = false;
+
+    /**
+     * Creates a new SparseArray containing no mappings.
+     */
+    public SparseWeakArray() {
+        this(10);
+    }
+
+    /**
+     * Creates a new SparseArray containing no mappings that will not
+     * require any additional memory allocation to store the specified
+     * number of mappings.
+     */
+    public SparseWeakArray(int initialCapacity) {
+        initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
+
+        mKeys = new int[initialCapacity];
+        mValues = new WeakReference[initialCapacity];
+        mSize = 0;
+    }
+
+    /**
+     * Gets the Object mapped from the specified key, or <code>null</code>
+     * if no such mapping has been made.
+     */
+    public E get(int key) {
+        return get(key, null);
+    }
+
+    /**
+     * Gets the Object mapped from the specified key, or the specified Object
+     * if no such mapping has been made.
+     */
+    public E get(int key, E valueIfKeyNotFound) {
+        int i = binarySearch(mKeys, 0, mSize, key);
+
+        if (i < 0 || mValues[i] == DELETED || mValues[i].get() == null) {
+            return valueIfKeyNotFound;
+        } else {
+            return (E) mValues[i].get();
+        }
+    }
+
+    /**
+     * Removes the mapping from the specified key, if there was any.
+     */
+    public void delete(int key) {
+        int i = binarySearch(mKeys, 0, mSize, key);
+
+        if (i >= 0) {
+            if (mValues[i] != DELETED) {
+                mValues[i] = DELETED;
+                mGarbage = true;
+            }
+        }
+    }
+
+    /**
+     * Alias for {@link #delete(int)}.
+     */
+    public void remove(int key) {
+        delete(key);
+    }
+
+    /**
+     * Removes the mapping at the specified index.
+     */
+    public void removeAt(int index) {
+        if (mValues[index] != DELETED) {
+            mValues[index] = DELETED;
+            mGarbage = true;
+        }
+    }
+
+    private void gc() {
+        // Log.e("SparseArray", "gc start with " + mSize);
+
+        int n = mSize;
+        int o = 0;
+        int[] keys = mKeys;
+        WeakReference<?>[] values = mValues;
+
+        for (int i = 0; i < n; i++) {
+            WeakReference<?> val = values[i];
+
+            // Don't keep any non DELETED values, but only the one that still have a valid
+            // reference.
+            if (val != DELETED && val.get() != null) {
+                if (i != o) {
+                    keys[o] = keys[i];
+                    values[o] = val;
+                }
+
+                o++;
+            }
+        }
+
+        mGarbage = false;
+        mSize = o;
+
+        // Log.e("SparseArray", "gc end with " + mSize);
+    }
+
+    /**
+     * Adds a mapping from the specified key to the specified value,
+     * replacing the previous mapping from the specified key if there
+     * was one.
+     */
+    public void put(int key, E value) {
+        int i = binarySearch(mKeys, 0, mSize, key);
+
+        if (i >= 0) {
+            mValues[i] = new WeakReference(value);
+        } else {
+            i = ~i;
+
+            if (i < mSize && (mValues[i] == DELETED || mValues[i].get() == null)) {
+                mKeys[i] = key;
+                mValues[i] = new WeakReference(value);
+                return;
+            }
+
+            if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) {
+                gc();
+
+                // Search again because indices may have changed.
+                i = ~binarySearch(mKeys, 0, mSize, key);
+            }
+
+            if (mSize >= mKeys.length) {
+                int n = ArrayUtils.idealIntArraySize(mSize + 1);
+
+                int[] nkeys = new int[n];
+                WeakReference<?>[] nvalues = new WeakReference[n];
+
+                // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
+                System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+                System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+                mKeys = nkeys;
+                mValues = nvalues;
+            }
+
+            if (mSize - i != 0) {
+                // Log.e("SparseArray", "move " + (mSize - i));
+                System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
+                System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
+            }
+
+            mKeys[i] = key;
+            mValues[i] = new WeakReference(value);
+            mSize++;
+        }
+    }
+
+    /**
+     * Returns the number of key-value mappings that this SparseArray
+     * currently stores.
+     */
+    public int size() {
+        if (mGarbage) {
+            gc();
+        }
+
+        return mSize;
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the key from the <code>index</code>th key-value mapping that this
+     * SparseArray stores.
+     */
+    public int keyAt(int index) {
+        if (mGarbage) {
+            gc();
+        }
+
+        return mKeys[index];
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, returns
+     * the value from the <code>index</code>th key-value mapping that this
+     * SparseArray stores.
+     */
+    public E valueAt(int index) {
+        if (mGarbage) {
+            gc();
+        }
+
+        return (E) mValues[index].get();
+    }
+
+    /**
+     * Given an index in the range <code>0...size()-1</code>, sets a new
+     * value for the <code>index</code>th key-value mapping that this
+     * SparseArray stores.
+     */
+    public void setValueAt(int index, E value) {
+        if (mGarbage) {
+            gc();
+        }
+
+        mValues[index] = new WeakReference(value);
+    }
+
+    /**
+     * Returns the index for which {@link #keyAt} would return the
+     * specified key, or a negative number if the specified
+     * key is not mapped.
+     */
+    public int indexOfKey(int key) {
+        if (mGarbage) {
+            gc();
+        }
+
+        return binarySearch(mKeys, 0, mSize, key);
+    }
+
+    /**
+     * Returns an index for which {@link #valueAt} would return the
+     * specified key, or a negative number if no keys map to the
+     * specified value.
+     * Beware that this is a linear search, unlike lookups by key,
+     * and that multiple keys can map to the same value and this will
+     * find only one of them.
+     */
+    public int indexOfValue(E value) {
+        if (mGarbage) {
+            gc();
+        }
+
+        for (int i = 0; i < mSize; i++)
+            if (mValues[i].get() == value)
+                return i;
+
+        return -1;
+    }
+
+    /**
+     * Removes all key-value mappings from this SparseArray.
+     */
+    public void clear() {
+        int n = mSize;
+        WeakReference<?>[] values = mValues;
+
+        for (int i = 0; i < n; i++) {
+            values[i] = null;
+        }
+
+        mSize = 0;
+        mGarbage = false;
+    }
+
+    /**
+     * Puts a key/value pair into the array, optimizing for the case where
+     * the key is greater than all existing keys in the array.
+     */
+    public void append(int key, E value) {
+        if (mSize != 0 && key <= mKeys[mSize - 1]) {
+            put(key, value);
+            return;
+        }
+
+        if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) {
+            gc();
+        }
+
+        int pos = mSize;
+        if (pos >= mKeys.length) {
+            int n = ArrayUtils.idealIntArraySize(pos + 1);
+
+            int[] nkeys = new int[n];
+            WeakReference<?>[] nvalues = new WeakReference[n];
+
+            // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
+            System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+            System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+            mKeys = nkeys;
+            mValues = nvalues;
+        }
+
+        mKeys[pos] = key;
+        mValues[pos] = new WeakReference(value);
+        mSize = pos + 1;
+    }
+
+    private boolean hasReclaimedRefs() {
+        for (int i = 0 ; i < mSize ; i++) {
+            if (mValues[i].get() == null) { // DELETED.get() never returns null.
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static int binarySearch(int[] a, int start, int len, int key) {
+        int high = start + len, low = start - 1, guess;
+
+        while (high - low > 1) {
+            guess = (high + low) / 2;
+
+            if (a[guess] < key)
+                low = guess;
+            else
+                high = guess;
+        }
+
+        if (high == start + len)
+            return ~(start + len);
+        else if (a[high] == key)
+            return high;
+        else
+            return ~high;
+    }
+
+    private int[] mKeys;
+    private WeakReference<?>[] mValues;
+    private int mSize;
+}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 39676b0..909605d 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -170,4 +170,6 @@
      * @return the event string sent by the supplicant.
      */
     public native static String waitForEvent();
+
+    public native static void enableBackgroundScan(boolean enable);
 }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index fc42ab8..676218e 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -112,9 +112,11 @@
     private String mLastBssid;
     private int mLastNetworkId;
     private boolean mEnableRssiPolling = false;
+    private boolean mEnableBackgroundScan = false;
     private int mRssiPollToken = 0;
     private int mReconnectCount = 0;
     private boolean mIsScanMode = false;
+    private boolean mScanResultIsPending = false;
 
     private boolean mBluetoothConnectionActive = false;
 
@@ -300,6 +302,8 @@
     static final int CMD_START_WPS                        = 89;
     /* Set the frequency band */
     static final int CMD_SET_FREQUENCY_BAND               = 90;
+    /* Enable background scan for configured networks */
+    static final int CMD_ENABLE_BACKGROUND_SCAN           = 91;
 
     /* Commands from/to the SupplicantStateTracker */
     /* Reset the supplicant state tracker */
@@ -823,6 +827,10 @@
        sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0));
     }
 
+    public void enableBackgroundScan(boolean enabled) {
+       sendMessage(obtainMessage(CMD_ENABLE_BACKGROUND_SCAN, enabled ? 1 : 0, 0));
+    }
+
     public void enableAllNetworks() {
         sendMessage(CMD_ENABLE_ALL_NETWORKS);
     }
@@ -1538,6 +1546,9 @@
                 case CMD_ENABLE_RSSI_POLL:
                     mEnableRssiPolling = (message.arg1 == 1);
                     break;
+                case CMD_ENABLE_BACKGROUND_SCAN:
+                    mEnableBackgroundScan = (message.arg1 == 1);
+                    break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
                 case CMD_UNLOAD_DRIVER:
@@ -1973,6 +1984,7 @@
                     eventLoggingEnabled = false;
                     setScanResults(WifiNative.scanResultsCommand());
                     sendScanResultsAvailableBroadcast();
+                    mScanResultIsPending = false;
                     break;
                 case CMD_PING_SUPPLICANT:
                     boolean ok = WifiNative.pingCommand();
@@ -2180,6 +2192,7 @@
                 case CMD_START_SCAN:
                     eventLoggingEnabled = false;
                     WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
+                    mScanResultIsPending = true;
                     break;
                 case CMD_SET_HIGH_PERF_MODE:
                     setHighPerfModeEnabledNative(message.arg1 == 1);
@@ -2681,8 +2694,8 @@
                      * back to CONNECT_MODE.
                      */
                     WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE);
-                    WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
-                    break;
+                    /* Have the parent state handle the rest */
+                    return NOT_HANDLED;
                     /* Ignore connection to same network */
                 case CMD_CONNECT_NETWORK:
                     int netId = message.arg1;
@@ -2771,21 +2784,35 @@
     }
 
     class DisconnectedState extends HierarchicalState {
+        private boolean mAlarmEnabled = false;
         @Override
         public void enter() {
             if (DBG) Log.d(TAG, getName() + "\n");
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
 
-            /**
-             * In a disconnected state, an infrequent scan that wakes
-             * up the device is needed to ensure a user connects to
-             * an access point on the move
+            /*
+             * We initiate background scanning if it is enabled, otherwise we
+             * initiate an infrequent scan that wakes up the device to ensure
+             * a user connects to an access point on the move
              */
-            long scanMs = Settings.Secure.getLong(mContext.getContentResolver(),
+            if (mEnableBackgroundScan) {
+                /* If a regular scan result is pending, do not initiate background
+                 * scan until the scan results are returned. This is needed because
+                 * initiating a background scan will cancel the regular scan and
+                 * scan results will not be returned until background scanning is
+                 * cleared
+                 */
+                if (!mScanResultIsPending) {
+                    WifiNative.enableBackgroundScan(true);
+                }
+            } else {
+                long scanMs = Settings.Secure.getLong(mContext.getContentResolver(),
                     Settings.Secure.WIFI_SCAN_INTERVAL_MS, DEFAULT_SCAN_INTERVAL_MS);
 
-            mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
+                mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                     System.currentTimeMillis() + scanMs, scanMs, mScanIntent);
+                mAlarmEnabled = true;
+            }
         }
         @Override
         public boolean processMessage(Message message) {
@@ -2800,6 +2827,10 @@
                         transitionTo(mScanModeState);
                     }
                     break;
+                case CMD_ENABLE_BACKGROUND_SCAN:
+                    mEnableBackgroundScan = (message.arg1 == 1);
+                    WifiNative.enableBackgroundScan(mEnableBackgroundScan);
+                    break;
                     /* Ignore network disconnect */
                 case NETWORK_DISCONNECTION_EVENT:
                     break;
@@ -2808,6 +2839,20 @@
                     setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
                     /* DriverStartedState does the rest of the handling */
                     return NOT_HANDLED;
+                case CMD_START_SCAN:
+                    /* Disable background scan temporarily during a regular scan */
+                    if (mEnableBackgroundScan) {
+                        WifiNative.enableBackgroundScan(false);
+                    }
+                    /* Handled in parent state */
+                    return NOT_HANDLED;
+                case SCAN_RESULTS_EVENT:
+                    /* Re-enable background scan when a pending scan result is received */
+                    if (mEnableBackgroundScan && mScanResultIsPending) {
+                        WifiNative.enableBackgroundScan(true);
+                    }
+                    /* Handled in parent state */
+                    return NOT_HANDLED;
                 default:
                     return NOT_HANDLED;
             }
@@ -2817,7 +2862,14 @@
 
         @Override
         public void exit() {
-            mAlarmManager.cancel(mScanIntent);
+            /* No need for a background scan upon exit from a disconnected state */
+            if (mEnableBackgroundScan) {
+                WifiNative.enableBackgroundScan(false);
+            }
+            if (mAlarmEnabled) {
+                mAlarmManager.cancel(mScanIntent);
+                mAlarmEnabled = false;
+            }
         }
     }