Merge "Import translations. DO NOT MERGE" into jb-mr1-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8711ad7..2287859 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -135,6 +135,7 @@
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/Disco*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing2_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index c455b7d..463a18c 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -990,7 +990,10 @@
         }
         name = arg;
         try {
-            if (mUm.createUser(name, 0) == null) {
+            final UserInfo info = mUm.createUser(name, 0);
+            if (info != null) {
+                System.out.println("Success: created user id " + info.id);
+            } else {
                 System.err.println("Error: couldn't create User.");
             }
         } catch (RemoteException e) {
diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java
new file mode 100644
index 0000000..70142ce
--- /dev/null
+++ b/core/java/android/service/dreams/Sandman.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.dreams;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+
+/**
+ * Internal helper for launching dreams to ensure consistency between the
+ * <code>UiModeManagerService</code> system service and the <code>Somnambulator</code> activity.
+ *
+ * @hide
+ */
+public final class Sandman {
+    private static final String TAG = "Sandman";
+
+    private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
+    private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
+
+    // The component name of a special dock app that merely launches a dream.
+    // We don't want to launch this app when docked because it causes an unnecessary
+    // activity transition.  We just want to start the dream.
+    private static final ComponentName SOMNAMBULATOR_COMPONENT =
+            new ComponentName("com.android.systemui", "com.android.systemui.Somnambulator");
+
+
+    // The sandman is eternal.  No one instantiates him.
+    private Sandman() {
+    }
+
+    /**
+     * Returns true if the specified dock app intent should be started.
+     * False if we should dream instead, if appropriate.
+     */
+    public static boolean shouldStartDockApp(Context context, Intent intent) {
+        ComponentName name = intent.resolveActivity(context.getPackageManager());
+        return name != null && !name.equals(SOMNAMBULATOR_COMPONENT);
+    }
+
+    /**
+     * Starts a dream manually.
+     */
+    public static void startDreamByUserRequest(Context context) {
+        startDream(context, false);
+    }
+
+    /**
+     * Starts a dream when docked if the system has been configured to do so,
+     * otherwise does nothing.
+     */
+    public static void startDreamWhenDockedIfAppropriate(Context context) {
+        if (!isScreenSaverEnabled(context)
+                || !isScreenSaverActivatedOnDock(context)) {
+            Slog.i(TAG, "Dreams currently disabled for docks.");
+            return;
+        }
+
+        startDream(context, true);
+    }
+
+    private static void startDream(Context context, boolean docked) {
+        try {
+            IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
+                    ServiceManager.getService(DreamService.DREAM_SERVICE));
+            if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
+                if (docked) {
+                    Slog.i(TAG, "Activating dream while docked.");
+
+                    // Wake up.
+                    // The power manager will wake up the system automatically when it starts
+                    // receiving power from a dock but there is a race between that happening
+                    // and the UI mode manager starting a dream.  We want the system to already
+                    // be awake by the time this happens.  Otherwise the dream may not start.
+                    PowerManager powerManager =
+                            (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+                    powerManager.wakeUp(SystemClock.uptimeMillis());
+                } else {
+                    Slog.i(TAG, "Activating dream by user request.");
+                }
+
+                // Dream.
+                dreamManagerService.dream();
+            }
+        } catch (RemoteException ex) {
+            Slog.e(TAG, "Could not start dream when docked.", ex);
+        }
+    }
+
+    private static boolean isScreenSaverEnabled(Context context) {
+        return Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
+                UserHandle.USER_CURRENT) != 0;
+    }
+
+    private static boolean isScreenSaverActivatedOnDock(Context context) {
+        return Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+                DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
+    }
+}
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index 37d84b3..357a16e 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -96,11 +96,26 @@
 
     // Template for JavaScript that performs AndroidVox actions.
     private static final String ACCESSIBILITY_ANDROIDVOX_TEMPLATE =
-            "cvox.AndroidVox.performAction('%1s')";
+            "(function() {" +
+                    "  if ((typeof(cvox) != 'undefined')"+
+                    "      && (typeof(cvox.ChromeVox) != 'undefined')" +
+                    "      && (typeof(cvox.AndroidVox) != 'undefined')" +
+                    "      && cvox.ChromeVox.isActive) {" +
+                    "    return cvox.AndroidVox.performAction('%1s');" +
+                    "  } else {" +
+                    "    return false;" +
+                    "  }" +
+                    "})()";
 
     // JS code used to shut down an active AndroidVox instance.
     private static final String TOGGLE_CVOX_TEMPLATE =
-            "javascript:(function() { cvox.ChromeVox.host.activateOrDeactivateChromeVox(%b); })();";
+            "javascript:(function() {" +
+                    "  if ((typeof(cvox) != 'undefined')"+
+                    "      && (typeof(cvox.ChromeVox) != 'undefined')" +
+                    "      && (typeof(cvox.ChromeVox.host) != 'undefined')) {" +
+                    "    cvox.ChromeVox.host.activateOrDeactivateChromeVox(%b);" +
+                    "  }" +
+                    "})();";
 
     /**
      * Creates an instance of the AccessibilityInjector based on
@@ -710,18 +725,7 @@
                 "javascript:(function() { %s.onResult(%d, %s); })();";
 
         // Time in milliseconds to wait for a result before failing.
-        // Based on recorded times, we have found that in a complex real-world
-        // web app (such as the desktop version of Gmail), there can be spikes
-        // of ~2600ms in the worst case. These are temporary spikes and are not
-        // repeatable; GMail eventually settles down to around ~60ms. The
-        // longest duration that is consistently repeatable is ~300ms when
-        // loading extremely large plain text documents in WebView.
-        // If this timeout hits, the navigation is considered to have "failed",
-        // meaning there is no content. Since the longer spikes are one-off
-        // events triggered by the page loading and itself running a large
-        // amount of JS, subsequent runs would succeed, so the worst impact
-        // is that the first run will look like it had not loaded yet.
-        private static final long RESULT_TIMEOUT = 1500;
+        private static final long RESULT_TIMEOUT = 5000;
 
         private final AtomicInteger mResultIdCounter = new AtomicInteger();
         private final Object mResultLock = new Object();
@@ -787,20 +791,26 @@
             while (true) {
                 try {
                     if (mResultId == resultId) {
+                        if (DEBUG)
+                            Log.w(TAG, "Received CVOX result");
                         return true;
                     }
                     if (mResultId > resultId) {
+                        if (DEBUG)
+                            Log.w(TAG, "Obsolete CVOX result");
                         return false;
                     }
                     final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
                     waitTimeMillis = RESULT_TIMEOUT - elapsedTimeMillis;
                     if (waitTimeMillis <= 0) {
+                        if (DEBUG)
+                            Log.w(TAG, "Timed out while waiting for CVOX result");
                         return false;
                     }
                     mResultLock.wait(waitTimeMillis);
                 } catch (InterruptedException ie) {
                     if (DEBUG)
-                        Log.w(TAG, "Timed out while waiting for CVOX result");
+                        Log.w(TAG, "Interrupted while waiting for CVOX result");
                     /* ignore */
                 }
             }
@@ -816,6 +826,8 @@
         @JavascriptInterface
         @SuppressWarnings("unused")
         public void onResult(String id, String result) {
+            if (DEBUG)
+                Log.w(TAG, "Saw CVOX result of '" + result + "'");
             final long resultId;
 
             try {
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index d68511c..7d0d0ba 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -5185,7 +5185,7 @@
         if (cm.hasPrimaryClip()) {
             Point cursorPoint = new Point(contentToViewX(mSelectCursorBase.x),
                     contentToViewY(mSelectCursorBase.y));
-            Point cursorTop = calculateCaretTop();
+            Point cursorTop = calculateBaseCaretTop();
             cursorTop.set(contentToViewX(cursorTop.x),
                     contentToViewY(cursorTop.y));
 
@@ -5229,17 +5229,22 @@
         return scale;
     }
 
+    private Point calculateBaseCaretTop() {
+        return calculateCaretTop(mSelectCursorBase, mSelectCursorBaseTextQuad);
+    }
+
+    private Point calculateDraggingCaretTop() {
+        return calculateCaretTop(mSelectDraggingCursor, mSelectDraggingTextQuad);
+    }
+
     /**
      * Assuming arbitrary shape of a quadralateral forming text bounds, this
      * calculates the top of a caret.
      */
-    private Point calculateCaretTop() {
-        float scale = scaleAlongSegment(mSelectCursorBase.x, mSelectCursorBase.y,
-                mSelectCursorBaseTextQuad.p4, mSelectCursorBaseTextQuad.p3);
-        int x = Math.round(scaleCoordinate(scale,
-                mSelectCursorBaseTextQuad.p1.x, mSelectCursorBaseTextQuad.p2.x));
-        int y = Math.round(scaleCoordinate(scale,
-                mSelectCursorBaseTextQuad.p1.y, mSelectCursorBaseTextQuad.p2.y));
+    private static Point calculateCaretTop(Point base, QuadF quad) {
+        float scale = scaleAlongSegment(base.x, base.y, quad.p4, quad.p3);
+        int x = Math.round(scaleCoordinate(scale, quad.p1.x, quad.p2.x));
+        int y = Math.round(scaleCoordinate(scale, quad.p1.y, quad.p2.y));
         return new Point(x, y);
     }
 
@@ -5269,12 +5274,20 @@
         return true;
     }
 
-    private void updateWebkitSelection() {
+    private void updateWebkitSelection(boolean isSnapped) {
         int handleId = (mSelectDraggingCursor == mSelectCursorBase)
                 ? HANDLE_ID_BASE : HANDLE_ID_EXTENT;
+        int x = mSelectDraggingCursor.x;
+        int y = mSelectDraggingCursor.y;
+        if (isSnapped) {
+            // "center" the cursor in the snapping quad
+            Point top = calculateDraggingCaretTop();
+            x = Math.round((top.x + x) / 2);
+            y = Math.round((top.y + y) / 2);
+        }
         mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
         mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT,
-                mSelectDraggingCursor.x, mSelectDraggingCursor.y, (Integer)handleId);
+                x, y, (Integer)handleId);
     }
 
     private void resetCaretTimer() {
@@ -5616,7 +5629,7 @@
                 Math.max(0, mEditTextContentBounds.top - buffer),
                 mEditTextContentBounds.right + buffer,
                 mEditTextContentBounds.bottom + buffer);
-        Point caretTop = calculateCaretTop();
+        Point caretTop = calculateBaseCaretTop();
         if (visibleRect.width() < mEditTextContentBounds.width()) {
             // The whole edit won't fit in the width, so use the caret rect
             if (mSelectCursorBase.x < caretTop.x) {
@@ -5947,10 +5960,12 @@
                         } else {
                             endScrollEdit();
                         }
+                        boolean snapped = false;
                         if (inCursorText || (mIsEditingText && !inEditBounds)) {
                             snapDraggingCursor();
+                            snapped = true;
                         }
-                        updateWebkitSelection();
+                        updateWebkitSelection(snapped);
                         if (!inCursorText && mIsEditingText && inEditBounds) {
                             // Visually snap even if we have moved the handle.
                             snapDraggingCursor();
@@ -6277,7 +6292,7 @@
                     int oldX = mSelectDraggingCursor.x;
                     int oldY = mSelectDraggingCursor.y;
                     mSelectDraggingCursor.set(selectionX, selectionY);
-                    updateWebkitSelection();
+                    updateWebkitSelection(false);
                     scrollEditText(scrollX, scrollY);
                     mSelectDraggingCursor.set(oldX, oldY);
                 }
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9ce7f8a..384f1ab 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1197,8 +1197,8 @@
     <!-- A coordinate in the Y dimension. -->
     <attr name="y" format="dimension" />
 
-    <!-- Specifies how to place the content of an object, both
-         on the x- and y-axis, within the object itself. -->
+    <!-- Specifies how an object should position its content, on both the X and Y axes,
+         within its own bounds.  -->
     <attr name="gravity">
         <!-- Push object to the top of its container, not changing its size. -->
         <flag name="top" value="0x30" />
@@ -1257,8 +1257,8 @@
     <!-- Reference to an array resource that will populate a list/adapter. -->
     <attr name="entries" format="reference" />
 
-    <!-- Standard gravity constant that a child can supply to its parent.
-         Defines how to place the view, both its x- and y-axis, within its parent view group. -->
+    <!-- Standard gravity constant that a child supplies to its parent.
+         Defines how the child view should be positioned, on both the X and Y axes, within its enclosing layout. -->
     <attr name="layout_gravity">
         <!-- Push object to the top of its container, not changing its size. -->
         <flag name="top" value="0x30" />
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
new file mode 100755
index 0000000..93c43da
--- /dev/null
+++ b/data/sounds/AudioPackage8.mk
@@ -0,0 +1,70 @@
+#
+# Audio Package 7 - Tuna
+# 
+# Include this file in a product makefile to include these audio files
+#
+# 
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+	$(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
+	$(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \
+	$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Bellatrix.ogg:system/media/audio/notifications/Bellatrix.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+	$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+	$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Themos.ogg:system/media/audio/ringtones/Themos.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
+	$(LOCAL_PATH)/ringtones/ogg/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg
diff --git a/data/sounds/alarms/ogg/Fermium.ogg b/data/sounds/alarms/ogg/Fermium.ogg
index fecc2ba..d8f6124 100644
--- a/data/sounds/alarms/ogg/Fermium.ogg
+++ b/data/sounds/alarms/ogg/Fermium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Hassium.ogg b/data/sounds/alarms/ogg/Hassium.ogg
index 260bf7d..793c269 100644
--- a/data/sounds/alarms/ogg/Hassium.ogg
+++ b/data/sounds/alarms/ogg/Hassium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Neptunium.ogg b/data/sounds/alarms/ogg/Neptunium.ogg
index b1ea741..d99f133 100644
--- a/data/sounds/alarms/ogg/Neptunium.ogg
+++ b/data/sounds/alarms/ogg/Neptunium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Osmium.ogg b/data/sounds/alarms/ogg/Osmium.ogg
new file mode 100644
index 0000000..4c76080
--- /dev/null
+++ b/data/sounds/alarms/ogg/Osmium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Promethium.ogg b/data/sounds/alarms/ogg/Promethium.ogg
new file mode 100644
index 0000000..2a195a3
--- /dev/null
+++ b/data/sounds/alarms/ogg/Promethium.ogg
Binary files differ
diff --git a/data/sounds/alarms/wav/Fermium.wav b/data/sounds/alarms/wav/Fermium.wav
index 0174884..56e57fc 100644
--- a/data/sounds/alarms/wav/Fermium.wav
+++ b/data/sounds/alarms/wav/Fermium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Hassium.wav b/data/sounds/alarms/wav/Hassium.wav
index e3992cf..17710b0 100644
--- a/data/sounds/alarms/wav/Hassium.wav
+++ b/data/sounds/alarms/wav/Hassium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Neptunium.wav b/data/sounds/alarms/wav/Neptunium.wav
index cf3684a..2b855e1 100644
--- a/data/sounds/alarms/wav/Neptunium.wav
+++ b/data/sounds/alarms/wav/Neptunium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Osmium.wav b/data/sounds/alarms/wav/Osmium.wav
new file mode 100755
index 0000000..2dcc47f
--- /dev/null
+++ b/data/sounds/alarms/wav/Osmium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Promethium.wav b/data/sounds/alarms/wav/Promethium.wav
new file mode 100755
index 0000000..08ea03e
--- /dev/null
+++ b/data/sounds/alarms/wav/Promethium.wav
Binary files differ
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index 273b5f7..fbff532 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -1,646 +1,902 @@
-page.title=Status Notifications
-parent.title=Notifications
-parent.link=index.html
+page.title=Notifications
 @jd:body
 
 <div id="qv-wrapper">
-  <div id="qv">
-    <h2>Quickview</h2>
-    <ul>
-      <li>A status notification allows your application to notify the user of an event
-without interupting their current activity</li>
-      <li>You can attach an intent to your notification that the system will initiate when the
-user clicks it</li>
-    </ul>
-
-    <h2>In this document</h2>
+<div id="qv">
+<h2>In this document</h2>
     <ol>
-      <li><a href="#Basics">The Basics</a></li>
-      <li><a href="#HandlingNotifications">Responding to Notifications</a></li>
-      <li><a href="#ManageYourNotifications">Managing your Notifications</a></li>
-      <li><a href="#CreateANotification">Creating a Notification</a>
-        <ol>
-          <li><a href="#Updating">Updating the notification</a></li>
-          <li><a href="#Sound">Adding a sound</a></li>
-          <li><a href="#Vibration">Adding vibration</a></li>
-          <li><a href="#Lights">Adding flashing lights</a></li>
-          <li><a href="#More">More features</a></li>
-        </ol>
-      </li>
-      <li><a href="#CustomExpandedView">Creating a Custom Notification Layout</a></li>
+        <li>
+            <a href="#NotificationUI">Notification Display Elements</a>
+        </li>
+        <li>
+        <a href="#CreateNotification">Creating a Notification</a>
+        </li>
+        <li>
+            <a href="#Managing">Managing Notifications</a>
+        </li>
+        <li>
+            <a href="#NotificationResponse">Preserving Navigation when Starting an Activity</a>
+        </li>
+        <li>
+            <a href="#Progress">Displaying Progress in a Notification</a>
+        </li>
+        <li>
+            <a href="#CustomNotification">Custom Notification Layouts</a>
+        </li>
     </ol>
     <h2>Key classes</h2>
     <ol>
-      <li>{@link android.app.Notification}</li>
-      <li>{@link android.app.NotificationManager}</li>
+        <li>{@link android.app.NotificationManager}</li>
+        <li>{@link android.support.v4.app.NotificationCompat}</li>
     </ol>
-    
-    <h2>See also</h2>
+    <h2>Videos</h2>
     <ol>
-      <li><a href="{@docRoot}design/patterns/notifications.html">Android
-Design: Notifications</a></li>
+        <li>
+            <a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s">
+            Notifications in 4.1</a>
+        </li>
     </ol>
-  </div>
+<h2>See also</h2>
+<ol>
+    <li>
+        <a href="{@docRoot}design/patterns/notifications.html">Android Design: Notifications</a>
+    </li>
+</ol>
 </div>
-
-<p>A status notification adds an icon to the system's status bar
-(with an optional ticker-text message) and a notification message in the notifications window.
-When the user selects the notification, Android fires an
-{@link android.content.Intent} that is defined by the {@link android.app.Notification} (usually to
-launch an {@link android.app.Activity}).
-You can also configure the notification to alert the user with a sound, a vibration, and flashing
-lights on the device.</p>
-
-<p>A status notification should be used for any case in
-which a background service needs to alert the user about an event that requires a response. A
-background service
-<strong>should never</strong> launch an activity on its own in order to receive user interaction.
-The service should instead create a status notification that will launch the activity
-when selected by the user.</p>
-
-<p>Figure 1 shows the status bar with a notification icon on the left side.</p>
-<img src="{@docRoot}images/status_bar.png" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> Status bar with a notification.</p>
-
-<p>Figure 2 shows the notification's message in the notifications window.</p>
-
-<img src="{@docRoot}images/notifications_window.png" alt="" />
-<p class="img-caption"><strong>Figure 2.</strong> The notifications window.</p>
-
-
+</div>
+<p>
+    A notification is a message you can display to the user outside of your application's
+    normal UI. When you tell the system to issue a notification, it first appears as an icon in the
+    <strong>notification area</strong>. To see the details of the notification, the user opens the
+    <strong>notification drawer</strong>. Both the notification area and the notification drawer
+    are system-controlled areas that the user can view at any time.
+</p>
+<img
+    id="figure1"
+    src="{@docRoot}images/ui/notifications/iconic_notification.png"
+    height="32"
+    alt="" />
+<p class="img-caption">
+    <strong>Figure 1.</strong> Notifications in the notification area.
+</p>
+<img id="figure2" src="{@docRoot}images/ui/notifications/normal_notification.png"
+    height="240" alt="" />
+<p class="img-caption">
+    <strong>Figure 2.</strong> Notifications in the notification drawer.
+</p>
 <div class="note design">
-<p><strong>Notification Design</strong></p>
-  <p>For design guidelines, read Android Design's <a
-href="{@docRoot}design/patterns/notifications.html">Notifications</a> guide.</p>
+    <p>
+        <strong>Notification Design</strong>
+    </p>
+    <p>
+        Notifications, as an important part of the Android UI, have their own design guidelines. To
+        learn how to design notifications and their interactions, read the Android Design Guide
+        <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> topic.
+    </p>
 </div>
-
-
-
-<h2 id="Basics">The Basics</h2>
-
-<p>An {@link android.app.Activity} or {@link android.app.Service} can initiate a status
-notification. Because an activity can perform actions only while it is
-running in the foreground and its window has focus, you will usually create status notifications
-from a
-service. This way, the notification can be created from the background,
-while the user is using another application or
-while the device is asleep. To create a notification, you must use two
-classes: {@link android.app.Notification} and {@link android.app.NotificationManager}.</p>
-
-<p>Use an instance of the {@link android.app.Notification} class to define the properties of your
-status notification, such as the status icon, the notification message, and extra settings
-such as a sound to play. The {@link android.app.NotificationManager} is an Android system service
-that executes and manages all status notifications. You do not instantiate the
-{@link android.app.NotificationManager} directly. In order
-to give it your {@link android.app.Notification}, you must retrieve a reference to the
-{@link android.app.NotificationManager} with
-{@link android.app.Activity#getSystemService(String) getSystemService()} and
-then, when you want to notify the user, pass it your {@link android.app.Notification} with
-{@link android.app.NotificationManager#notify(int,Notification) notify()}. </p>
-
-<p>To create a status notification:</p>
-<ol>
-  <li>Get a reference to the {@link android.app.NotificationManager}:
-<pre>
-String ns = Context.NOTIFICATION_SERVICE;
-NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
-</pre>
-  </li>
-  <!-- use Notification.Builder in 3.0 -->
-  <li>Instantiate the {@link android.app.Notification}:
-<pre>
-int icon = R.drawable.notification_icon;
-CharSequence tickerText = "Hello";
-long when = System.currentTimeMillis();
-
-Notification notification = new Notification(icon, tickerText, when);
-</pre>
-  </li>
-  <li>Define the notification's message and {@link android.app.PendingIntent}:
-<pre>
-Context context = getApplicationContext();
-CharSequence contentTitle = "My notification";
-CharSequence contentText = "Hello World!";
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-
-notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
-</pre>
-  </li>
-  <li>Pass the {@link android.app.Notification} to the {@link android.app.NotificationManager}:
-<pre>
-private static final int HELLO_ID = 1;
-
-mNotificationManager.notify(HELLO_ID, notification);
-</pre>
-  <p>That's it. Your user has now been notified.</p>
-  </li>
-</ol>
-
-
-<h2 id="HandlingNotifications">Responding to Notifications</h2>
-
-<p>A central part of the user's experience with a notification revolves around
-how it interacts with the application's UI flow.  You must implement
-this correctly to provide a consistent user experience within your app.</p>
-
-<p>Two typical examples of notifications are provided by Calendar, which can send out
-notifications of upcoming events, and Email, which can send out notifications
-when new messages arrive.  These represent the two recommended patterns for handling
-notifications: either launching into an activity that is separate from the
-main application, or launching an entirely new instance of the application
-showing the appropriate point for the notification.</p>
-
-<p>The following scenario shows how the activity stack should work
-in these two typical notification flows, first handling a Calendar notification:
+<p class="note">
+    <strong>Note:</strong> This guide refers to the
+    {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class
+    in the version 4 <a href="{@docRoot}tools/extras/support-library.html">Support Library</a>.
+    The class {@link android.app.Notification.Builder Notification.Builder} was added in API
+    level 11.
 </p>
-
-<ol>
-  <li>User is creating a new event in Calendar. They realize they
-    need to copy part of an email message into this event.
-  </li>
-  <li>
-    The user chooses Home &gt; Email.
-  </li>
-  <li>
-    While in Email, they receive a notification from Calendar for an upcoming
-    meeting.
-  </li>
-  <li>
-    So they choose that notification, which takes them to a
-    dedicated Calendar activity that displays brief details of the
-    upcoming meeting.
-  </li>
-  <li>
-    The user has seen enough to know they have a meeting coming up,
-    so they press the <em>Back</em> button.  They are now returned to Email, which
-    is where they were when they took the notification.
-  </li>
-</ol>
-
-<p>Handling an Email notification:</p>
-
-<ol>
-  <li>
-    The user is currently in Email composing a message, and needs to
-    check a date in their calendar.
-  </li>
-  <li>
-    The user chooses Home &gt; Calendar.
-  </li>
-  <li>
-    While in Calendar, they receive a notification from Email about a new
-    message.
-  </li>
-  <li>
-    They select the notification, which brings them to Email with the message
-    details displayed.  This has replaced what they were previously doing
-    (writing an e-mail), but that message is still saved in their drafts.
-  </li>
-  <li>
-    The user presses <em>Back</em> once to go to the message list (the typical flow in the
-    Email app), and press <em>Back</em> again to return to Calendar as they left it.
-  </li>
-</ol>
-
-<p>In an Email style of notification, the UI launched by the notification
-shows the main application in a state representing that notification.
-For example, when the Email application comes to the foreground from its
-notification, it displays either the conversion list or a specific
-conversation depending on whether there are multiple or only one new
-email.  To achieve this, we want to completely replace whatever current
-state the application is in with a new activity stack representing the
-new notification state.</p>
-
-<p>The following code illustrates how to show this kind of notification.  Of
-most interest is the <code>makeMessageIntentStack()</code> method, which constructs
-an array of intents representing the app's new activity stack for this state.
-(If you are using fragments, you may need to initialize your fragment and
-app state so that pressing <em>Back</em> will switch the UI back to its parent state.)
-The core of this is the {@link android.content.Intent#makeRestartActivityTask
-Intent.makeRestartActivityTask()} method, which constructs the root activity
-of the stack with the appropriate flags, such as
-{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK Intent.FLAG_ACTIVITY_CLEAR_TASK}.</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
-  app_notification}
-
-<p>In a Calendar style of notification, the UI launched by the notification
-is a dedicated activity that is not part of the normal application flow.
-For example, when the user receives a Calendar notification, choosing that
-notification starts a special activity that displays a list
-of upcoming calendar events &mdash; this view is available only
-from the notification, not through the Calendar's normal user
-interface.</p>
-
-<p>The code for posting this type of notification is very straight-forward; it
-is like the above, but the {@link android.app.PendingIntent} is for just a single
-activity, our dedicated notification activity.</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
-  interstitial_notification}
-
-<p>This is not enough, however.  Normally Android considers all activities within
-an application to be part of that application's UI flow, so simply launching the
-activity like this can cause it to be mixed with your normal application back stack
-in undesired ways.  To make it behave correctly, in the manifest declaration
-for the activity the attributes 
-<code>android:launchMode="singleTask"</code>,
-<code>android:taskAffinity=""</code> and
-<code>android:excludeFromRecents="true"</code>
-must be set.  The full activity declaration for this sample is:</p>
-
-{@sample development/samples/ApiDemos/AndroidManifest.xml interstitial_affinity}
-
-<p>You must be careful when launching other activities from this initial activity,
-because this is not a top-level part of the application, does not appear in
-recents, and needs to be relaunched at any point from the notification with new data
-to show.  This best approach is to make sure any activity launched from it is
-launched in its own task.  When doing this care must be taken to make sure this
-new task interacts well with the current state of your exiting application's
-task.  This is essentially
-the same as switching to the main application as described for the Email style
-notification shown before.  Given the <code>makeMessageIntentStack()</code>
-method previously shown, handling a click then would look something like this:</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageInterstitial.java
-  app_launch}
-
-<h2 id="ManageYourNotifications">Managing your Notifications</h2>
-
-<p>The {@link android.app.NotificationManager} is a system service that manages all
-notifications. You must retrieve a reference to it with the
-{@link android.app.Activity#getSystemService(String) getSystemService()} method.
-For example:</p>
-<pre>
-String ns = Context.NOTIFICATION_SERVICE;
-NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
-</pre>
-
-<p>When you want to deliver your status notification, pass the {@link android.app.Notification}
-to the {@link android.app.NotificationManager} with {@link
-android.app.NotificationManager#notify(int,Notification)}.
-The first parameter is the unique ID for the notification and the second is the {@link
-android.app.Notification} object.
-The ID uniquely identifies the notification from within your
-application. The ID is necessary if you need to update the notification or (if
-your application manages different kinds of notifications) select the appropriate action
-when the user returns to your application via the intent defined in the notification.</p>
-
-<p>To clear the status notification when the user selects it from the notifications
-window, add the "FLAG_AUTO_CANCEL" flag to your {@link android.app.Notification}. You can
-also clear it manually with {@link android.app.NotificationManager#cancel(int)}, passing it the
-notification ID, or clear all your notifications with {@link
-android.app.NotificationManager#cancelAll()}.</p>
-
-
-<h2 id="CreateANotification">Creating a Notification</h2>
-
-<p>A {@link android.app.Notification} object defines the details of the notification
-message that is displayed in the status bar and notifications window, and any other
-alert settings, such as sounds and blinking lights.</p>
-
-<p>A status notification <em>requires</em> all of the following:</p>
-<ul>
-  <li>An icon for the status bar</li>
-  <li>A title and message, unless you define a
-    <a href="#CustomExpandedView">custom notification layout</a></li>
-  <li>A {@link android.app.PendingIntent}, to be fired when the notification is selected</li>
-</ul>
-<p>Optional settings for the status notification include:</p>
-<ul>
-  <li>A ticker-text message for the status bar</li>
-  <li>An alert sound</li>
-  <li>A vibrate setting</li>
-  <li>A flashing LED setting</li>
-</ul>
-
-<p>The starter-kit for a new notification includes the
-{@link android.app.Notification#Notification(int,CharSequence,long)} constructor and the
-{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)}
-method. These define all the required settings for a notification.
-The following snippet demonstrates a basic notification setup:</p>
-<pre>
-int icon = R.drawable.notification_icon;        // icon from resources
-CharSequence tickerText = "Hello";              // ticker-text
-long when = System.currentTimeMillis();         // notification time
-Context context = getApplicationContext();      // application Context
-CharSequence contentTitle = "My notification";  // message title
-CharSequence contentText = "Hello World!";      // message text
-
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-
-// the next two lines initialize the Notification, using the configurations above
-Notification notification = new Notification(icon, tickerText, when);
-notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
-</pre>
-
-
-<h3 id="Updating">Updating the notification</h3>
-
-<p>You can update the information in your status notification as events
-continue to occur in your application. For example, when a new SMS text message arrives
-before previous messages have been read, the Messaging application updates the existing
-notification to display the total number of new messages received.
-This practice of updating an existing notification is much better than adding new
-notifications, because it avoids clutter in the notifications window.</p>
-
-<p>Because each notification is uniquely identified
-by the {@link android.app.NotificationManager} with an integer ID, you can revise the notification
-by calling {@link
-android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} with new values, change some field values of the notification, and then call
-{@link android.app.NotificationManager#notify(int,Notification) notify()} again.</p>
-
-<p>You can revise each property with the object member fields
-(except for the {@link android.content.Context} and the notification title and text). You
-should always revise the text message when you update the notification by calling
-{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} with new values for <var>contentTitle</var> and <var>contentText</var>.
-Then call {@link android.app.NotificationManager#notify(int,Notification) notify()} to update the
-notification. (Of course, if you've created a <a href="#CustomExpandedView">custom notification
-layout</a>, then updating these title and text values has no effect.)</p>
-
-
-<h3 id="Sound">Adding a sound</h3>
-
-<p>You can alert the user with the default notification sound
-(which is defined by the user) or with a sound specified by your application.</p>
-
-<p>To use the user's default sound, add "DEFAULT_SOUND" to the <var>defaults</var> field:</p>
-<pre>
-notification.defaults |= Notification.DEFAULT_SOUND;
-</pre>
-
-<p>To use a different sound with your notifications, pass a Uri reference to the
-<var>sound</var> field.
-The following example uses a known audio file saved to the device SD card:</p>
-<pre>
-notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");
-</pre>
-
-<p>In the next example, the audio file is chosen from the internal
-{@link android.provider.MediaStore.Audio.Media MediaStore}'s {@link android.content.ContentProvider}:</p>
-<pre>
-notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
-</pre>
-
-<p>In this case, the exact ID of the media file ("6") is known and appended to the content
-{@link android.net.Uri}. If you don't know the exact ID, you must query all the
-media available in the {@link android.provider.MediaStore} with a {@link
-android.content.ContentResolver}.
-See the <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
-documentation for more information on using a ContentResolver.</p>
-
-<p>If you want the sound to continuously repeat until the user responds to the notification
-or the notification is cancelled, add {@link android.app.Notification#FLAG_INSISTENT} to the
-<var>flags</var> field.</p>
-
-<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
-{@link android.app.Notification#DEFAULT_SOUND}, then the default sound overrides any sound defined
-by the <var>sound</var> field.</p>
-
-
-<h3 id="Vibration">Adding vibration</h3>
-
-<p>You can alert the user with the the default
-vibration pattern or with a vibration pattern defined by your application.</p>
-
-<p>To use the default pattern, add {@link android.app.Notification#DEFAULT_VIBRATE} to the
-<var>defaults</var> field:</p>
-<pre>
-notification.defaults |= Notification.DEFAULT_VIBRATE;
-</pre>
-
-<p>To define your own vibration pattern, pass an array of <em>long</em> values to the
-<var>vibrate</var> field:</p>
-<pre>
-long[] vibrate = {0,100,200,300};
-notification.vibrate = vibrate;
-</pre>
-
-<p>The long array defines the alternating pattern for the length of vibration off and on
-(in milliseconds). The first value is how long to wait (off) before beginning, the second
-value is the length of the first vibration, the third is the next length off, and so on.
-The pattern can be as long as you like, but it can't be set to repeat.
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="NotificationUI">Notification Display Elements</h2>
+<p>
+    Notifications in the notification drawer appear in two main visual styles, normal view and
+    big view.
 </p>
-
-<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
-{@link android.app.Notification#DEFAULT_VIBRATE}, then the default vibration overrides any vibration
-defined by the
-<var>vibrate</var> field.</p>
-
-
-<h3 id="Lights">Adding flashing lights</h3>
-
-<p>To alert the user by flashing LED lights, you can implement the default
-light pattern (if available), or define your own color and pattern for the lights.</p>
-
-<p>To use the default light setting, add {@link android.app.Notification#DEFAULT_LIGHTS} to the
-<var>defaults</var> field:</p>
-<pre>
-notification.defaults |= Notification.DEFAULT_LIGHTS;
-</pre>
-
-<p>To define your own color and pattern, define a value for the <var>ledARGB</var> field
-(for the color), the <var>ledOffMS</var> field (length of time, in milliseconds, to
-keep the light off), the <var>ledOnMS</var> (length of time, in milliseconds, to keep the light on),
-and also add {@link android.app.Notification#FLAG_SHOW_LIGHTS} to the <var>flags</var> field:</p>
-<pre>
-notification.ledARGB = 0xff00ff00;
-notification.ledOnMS = 300;
-notification.ledOffMS = 1000;
-notification.flags |= Notification.FLAG_SHOW_LIGHTS;
-</pre>
-
-<p>In this example, the green light repeatedly flashes on for 300 milliseconds and
-turns off for one second. Not every color in the spectrum is supported by the
-device LEDs, and not every device supports the same colors, so the hardware
-estimates to the best of its ability. Green is the most common notification color.</p>
-
-
-<h3 id="More">More features</h3>
-
-<p>You can add several more features to your notifications
-using {@link android.app.Notification} fields and flags. Some useful features include the
-following:</p>
-
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="NormalNotify">Normal view</h3>
+<p>
+    A notification in normal view appears in an area that's up to 64 dp tall. Even if you create a
+    notification with a big view style, it will appear in normal view until it's expanded. This
+    is an example of a normal view:
+</p>
+<img
+    src="{@docRoot}images/ui/notifications/normal_notification_callouts.png"
+    alt=""
+    height="204"
+    id="figure3" />
+<p class="img-caption">
+  <strong>Figure 3.</strong> Notification in normal view.
+</p>
+<p>
+    The callouts in the illustration refer to the following:
+</p>
+<ol>
+    <li>Content title</li>
+    <li>Large icon</li>
+    <li>Content text</li>
+    <li>Content info</li>
+    <li>Small icon</li>
+    <li>
+        Time that the notification was issued. You can set an explicit value with
+        {@link android.support.v4.app.NotificationCompat.Builder#setWhen setWhen()}; if you don't
+        it defaults to the time that the system received the notification.
+    </li>
+</ol>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="BigNotify">Big view</h3>
+<p>
+    A notification's big view appears only when the notification is expanded, which happens when the
+    notification is at the top of the notification drawer, or when the user expands the
+    notification with a gesture.
+</p>
+<p>
+    The following screenshot shows an inbox-style notification:
+</p>
+<img src="{@docRoot}images/ui/notifications/bigpicture_notification_callouts.png"
+    alt=""
+    height="240"
+    id="figure4" />
+<p class="img-caption">
+  <strong>Figure 4.</strong> Big view notification.
+</p>
+<p>
+    Notice that the big view shares most of its visual elements with the normal view. The
+    only difference is callout number 7, the details area. Each big view style sets this area in
+    a different way. The available styles are:
+</p>
 <dl>
-  <dt>{@link android.app.Notification#FLAG_AUTO_CANCEL} flag</dt>
-  <dd>Add this to the <var>flags</var> field to automatically cancel the notification
-  after it is selected from the notifications window.</dd>
-  <dt>{@link android.app.Notification#FLAG_INSISTENT} flag</dt>
-  <dd>Add this to the <var>flags</var> field to repeat the audio until the
-  user responds.</dd>
-  <dt>{@link android.app.Notification#FLAG_ONGOING_EVENT} flag</dt>
-  <dd>Add this to the <var>flags</var> field to group the notification under the "Ongoing"
-  title in the notifications window. This indicates that the application is on-going &mdash;
-  its processes are still running in the background, even when the application is not
-  visible (such as with music or a phone call).</dd>
-  <dt>{@link android.app.Notification#FLAG_NO_CLEAR} flag</dt>
-  <dd>Add this to the <var>flags</var> field to indicate that the notification should
-  <em>not</em> be cleared by the "Clear notifications" button. This is particularly useful if
-  your notification is on-going.</dd>
-  <dt>{@link android.app.Notification#number} field</dt>
-  <dd>This value indicates the current number of events represented by the notification.
-  The appropriate number is overlaid on top of the status icon.
-  If you intend to use this field, then you must start with "1" when the Notification is first
-  created. (If you change the value from zero to anything greater during an update, the number
-  is not shown.)</dd>
-  <dt>{@link android.app.Notification#iconLevel} field</dt>
-  <dd>This value indicates the current level of a
-  {@link android.graphics.drawable.LevelListDrawable} that is used for the notification icon.
-  You can animate the icon in the status bar by changing this value to correlate with the
-  drawable's defined in a LevelListDrawable. See the {@link android.graphics.drawable.LevelListDrawable}
-  reference for more information.</dd>
+    <dt>
+        Big picture style
+    </dt>
+    <dd>
+        The details area contains a bitmap up to 256 dp tall in its detail section.
+    </dd>
+    <dt>
+        Big text style
+    </dt>
+    <dd>
+        Displays a large text block in the details section.
+    </dd>
+    <dt>
+        Inbox style
+    </dt>
+    <dd>
+        Displays lines of text in the details section.
+    </dd>
 </dl>
+<p>
+    All of the big view styles also have the following content options that aren't
+    available in normal view:
+</p>
+<dl>
+    <dt>
+        Big content title
+    </dt>
+    <dd>
+        Allows you to override the normal view's content title with a title that appears only in
+        the expanded view.
+    </dd>
+    <dt>
+        Summary text
+    </dt>
+    <dd>
+        Allows you to add a line of text below the details area.
+    </dd>
+</dl>
+<p>
+    Applying a big view style to a notification is described in the section
+    <a href="#ApplyStyle">Applying a big view style to a notification</a>.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="CreateNotification">Creating a Notification</h2>
+<p>
+    You specify the UI information and actions for a notification in a
+    {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} object.
+    To create the notification itself, you call
+    {@link android.support.v4.app.NotificationCompat.Builder#build
+    NotificationCompat.Builder.build()}, which returns a {@link android.app.Notification} object
+    containing your specifications.
+    To issue the notification, you pass the {@link android.app.Notification} object to the system
+    by calling {@link android.app.NotificationManager#notify NotificationManager.notify()}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Required">Required notification contents</h3>
+<p>
+    A {@link android.app.Notification} object <em>must</em> contain the following:
+</p>
+<ul>
+    <li>
+        A small icon, set by
+        {@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
+    </li>
+    <li>
+        A title, set by
+        {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
+    </li>
+    <li>
+        Detail text, set by
+        {@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
+    </li>
+</ul>
+<h3 id="Optional">Optional notification contents and settings</h3>
+<p>
+    All other notification settings and contents are optional. To learn more about them,
+    see the reference documentation for {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Actions">Notification actions</h3>
+<p>
+    Although they're optional, you should add at least one action to your notification.
+    An action allows users to go directly from the notification to an
+    {@link android.app.Activity} in your application, where they can look at one or more events
+    or do further work.
+</p>
+<p>
+    A notification can provide multiple actions. You should always define the action that's
+    triggered when the user touches the notification; usually this action opens an
+    {@link android.app.Activity} in your application. You can also add buttons to the notification
+    that perform additional actions such as snoozing an alarm or responding immediately to a text
+    message.
+</p>
+<p>
+    Inside a {@link android.app.Notification}, the action itself is defined by a
+    {@link android.app.PendingIntent} containing an {@link android.content.Intent} that starts
+    an {@link android.app.Activity} in your application. To associate the
+    {@link android.app.PendingIntent} with a gesture, call the appropriate method of
+    {@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start
+    {@link android.app.Activity} when the user touches the notification text in
+    the notification drawer, you add the {@link android.app.PendingIntent} by calling
+    {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
+</p>
+<p>
+    Starting an {@link android.app.Activity} when the user touches the notification is the most
+    common action scenario. You can also start an {@link android.app.Activity} when the user
+    dismisses an {@link android.app.Activity}, and you can start an {@link android.app.Activity}
+    from an action button. To learn more, read the reference guide for
+    {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="SimpleNotification">Creating a simple notification</h3>
+<p>
+    The following snippet illustrates a simple notification that specifies an activity to open when
+    the user touches the notification. Notice that the code creates a
+    {@link android.support.v4.app.TaskStackBuilder} object and uses it to create the
+    {@link android.app.PendingIntent} for the action. This pattern is explained in more detail
+    in the section <a href="#NotificationResponse">
+    Preserving Navigation when Starting an Activity</a>:
+</p>
+<pre>
+NotificationCompat.Builder mBuilder =
+        new NotificationCompat.Builder(this)
+        .setSmallIcon(R.drawable.notification_icon)
+        .setContentTitle("My notification")
+        .setContentText("Hello World!");
+// Creates an explicit intent for an Activity in your app
+Intent resultIntent = new Intent(this, ResultActivity.class);
 
-<p>See the {@link android.app.Notification} class reference for more information about additional
-features that you can customize for your application.</p>
+// The stack builder object will contain an artificial back stack for the
+// started Activity.
+// This ensures that navigating backward from the Activity leads out of
+// your application to the Home screen.
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack for the Intent (but not the Intent itself)
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent that starts the Activity to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+PendingIntent resultPendingIntent =
+        stackBuilder.getPendingIntent(
+            0,
+            PendingIntent.FLAG_UPDATE_CURRENT
+        );
+mBuilder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// mId allows you to update the notification later on.
+mNotificationManager.notify(mId, mBuilder.build());
+</pre>
+<p>That's it. Your user has now been notified.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ApplyStyle">Applying a big view style to a notification</h3>
+<p>
+    To have a notification appear in a big view when it's expanded, first create a
+    {@link android.support.v4.app.NotificationCompat.Builder} object with the normal view options
+    you want. Next, call {@link android.support.v4.app.NotificationCompat.Builder#setStyle
+    Builder.setStyle()} with a big view style object as its argument.
+</p>
+<p>
+    For example, the following code snippet demonstrates how to alter the notification created
+    in the previous snippet to use the Inbox big view style:
+</p>
+<pre>
+NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
+    .setSmallIcon(R.drawable.notification_icon)
+    .setContentTitle("Event tracker")
+    .setContentText("Events received")
+NotificationCompat.InboxStyle inboxStyle =
+        new NotificationCompat.InboxStyle();
+String[] events = new String[6];
+// Sets a title for the Inbox style big view
+inboxStyle.SetBigContentTitle("Event tracker details:");
+...
+// Moves events into the big view
+for (int i=0; i &lt; events.length; i++) {
 
-
-<h2 id="CustomExpandedView">Creating a Custom Notification Layout</h2>
-
-<div class="figure" style="width:200px;margin-top:0">
-<img src="{@docRoot}images/custom_message.png" alt="" />
-<p class="img-caption"><strong>Figure 3.</strong> Notification with a custom layout.</p>
-</div>
-
-<p>By default, the notification that appears in the notifications window includes a title
-and the message text.
-These are defined by the <var>contentTitle</var> and <var>contentText</var>
-parameters of the {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} method. However, you can also define a custom layout for the
-notification using
-{@link android.widget.RemoteViews}. Figure 3 shows an example of a
-custom notification layout. It looks similar to the default notification, but is
-actually created with a custom XML layout.</p>
-
-<p>To define your own layout for the notification,
-instantiate a {@link android.widget.RemoteViews} object that inflates a custom layout file, then
-pass the {@link android.widget.RemoteViews} to the <var>contentView</var> field of your
-Notification.</p>
-
-<p>Creating a custom notification layout is best understood with an example:</p>
-
+    inboxStyle.addLine(events[i]);
+}
+// Moves the big view style object into the notification object.
+mBuilder.setStyle(inBoxStyle);
+...
+// Issue the notification here.
+</pre>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Managing">Managing Notifications</h2>
+<p>
+    When you need to issue a notification multiple times for the same type of event, you
+    should avoid making a completely new notification. Instead, you should consider updating a
+    previous notification, either by changing some of its values or by adding to it, or both.
+</p>
+<p>
+    For example, Gmail notifies the user that new emails have arrived by increasing its count of
+    unread messages and by adding a summary of each email to the notification. This is called
+    "stacking" the notification; it's described in more detail in the
+    <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design guide.
+</p>
+<p>
+    The following section describes how to update notifications and also how to remove them.
+</p>
+<h3 id="Updating">Updating notifications</h3>
+<p>
+    To set up a notification so it can be updated, issue it with a notification ID by
+    calling {@link android.app.NotificationManager#notify(int, Notification)
+    NotificationManager.notify(ID, notification)}. To update this notification once you've issued
+    it, update or create a {@link android.support.v4.app.NotificationCompat.Builder} object,
+    build a {@link android.app.Notification} object from it, and issue the
+    {@link android.app.Notification} with the same ID you used previously. If
+    the previous notification is still visible, the system updates it from the contents of
+    the {@link android.app.Notification} object. If the previous notification has been dismissed, a
+    new notification is created instead.
+</p>
+<p>
+    The following snippet demonstrates a notification that is updated to reflect the
+    number of events that have occurred. It stacks the notification, showing a summary:
+</p>
+<pre>
+mNotificationManager =
+        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Sets an ID for the notification, so it can be updated
+int notifyID = 1;
+mNotifyBuilder = new NotificationCompat.Builder(this)
+    .setContentTitle("New Message")
+    .setContentText("You've received new messages.")
+    .setSmallIcon(R.drawable.ic_notify_status)
+numMessages = 0;
+// Start of a loop that processes data and then notifies the user
+...
+    mNotifyBuilder.setContentText(currentText)
+        .setNumber(++numMessages);
+    // Because the ID remains unchanged, the existing notification is
+    // updated.
+    mNotificationManager.notify(
+            notifyID,
+            mNotifyBuilder.build());
+...
+</pre>
+<p>
+    This produces a notification that looks like this:
+</p>
+<img
+    id="figure5"
+    src="{@docRoot}images/ui/notifications/updated_notification.png"
+    alt=""
+    height="118"/>
+<p class="img-caption">
+  <strong>Figure 5.</strong> Updated notification displayed in the notification drawer.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Removing">Removing notifications</h3>
+<p>
+    Notifications remain visible until one of the following happens:
+</p>
+<ul>
+    <li>
+        The user dismisses the notification either individually or by using "Clear All" (if
+        the notification can be cleared).
+    </li>
+    <li>
+        The user touches the notification, and you called
+        {@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} when
+        you created the notification.
+    </li>
+    <li>
+        You call {@link android.app.NotificationManager#cancel(int) cancel()} for a specific
+        notification ID. This method also deletes ongoing notifications.
+    </li>
+    <li>
+        You call {@link android.app.NotificationManager#cancelAll() cancelAll()}, which removes
+        all of the notifications you previously issued.
+    </li>
+</ul>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="NotificationResponse">Preserving Navigation when Starting an Activity</h2>
+<p>
+    When you start an {@link android.app.Activity} from a notification, you must preserve the
+    user's expected navigation experience. Clicking <i>Back</i> should take the user back through
+    the application's normal work flow to the Home screen, and clicking <i>Recents</i> should show
+    the {@link android.app.Activity} as a separate task. To preserve the navigation experience, you
+    should start the {@link android.app.Activity} in a fresh task. How you set up the
+    {@link android.app.PendingIntent} to give you a fresh task depends on the nature of the
+    {@link android.app.Activity} you're starting. There are two general situations:
+</p>
+<dl>
+    <dt>
+        Regular activity
+    </dt>
+    <dd>
+        You're starting an {@link android.app.Activity} that's part of the application's normal
+        workflow. In this situation, set up the {@link android.app.PendingIntent} to
+        start a fresh task, and provide the {@link android.app.PendingIntent} with a back stack
+        that reproduces the application's normal <i>Back</i> behavior.
+        <p>
+            Notifications from the Gmail app demonstrate this. When you touch a notification for
+            a single email message, you see the message itself. Touching <b>Back</b> takes you
+            backwards through Gmail to the Home screen, just as if you had entered Gmail from the
+            Home screen rather than entering it from a notification.
+        </p>
+        <p>
+            This happens regardless of the application you were in when you touched the
+            notification. For example, if you're in Gmail composing a message, and you click a
+            notification for a single email, you go immediately to that email. Touching <i>Back</i>
+            takes you to the inbox and then the Home screen, rather than taking you to the
+            message you were composing.
+        </p>
+    </dd>
+    <dt>
+        Special activity
+    </dt>
+    <dd>
+        The user only sees this {@link android.app.Activity} if it's started from a notification.
+        In a sense, the {@link android.app.Activity} extends the notification by providing
+        information that would be hard to display in the notification itself. For this situation,
+        set up the {@link android.app.PendingIntent} to start in a fresh task. There's no need to
+        create a back stack, though, because the started {@link android.app.Activity} isn't part of
+        the application's activity flow. Clicking <i>Back</i> will still take the user to the
+        Home screen.
+    </dd>
+</dl>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="DirectEntry">Setting up a regular activity PendingIntent</h3>
+<p>
+    To set up a {@link android.app.PendingIntent} that starts a direct entry
+    {@link android.app.Activity}, follow these steps:
+</p>
 <ol>
-  <li>Create the XML layout for the notification.
-    For example, the following layout is called <code>custom_notification.xml</code>:
+    <li>
+        Define your application's {@link android.app.Activity} hierarchy in the manifest.
+        <ol style="list-style-type: lower-alpha;">
+            <li>
+                Add support for API versions 15 and earlier. To do this, specify the parent of the
+                {@link android.app.Activity} you're starting by adding a
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
+                element as the child of the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>.
+                <p>
+                    For this element, set
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
+                    Set
+<code><a href="{@docRoot}/guide/topics/manifest/meta-data-element.html#val">android:value</a>="&lt;parent_activity_name&gt;"</code>
+                    where <code>&lt;parent_activity_name&gt;</code> is the value of
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
+                    for the parent
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+                    element. See the following XML for an example.
+                </p>
+            </li>
+            <li>
+                Also add support for API versions 16 and later. To do this, add the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
+                attribute to the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+                element of the {@link android.app.Activity} you're starting.
+            </li>
+        </ol>
+        <p>
+            The final XML should look like this:
+        </p>
 <pre>
-&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/layout"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:padding="10dp" >
-    &lt;ImageView android:id="@+id/image"
-        android:layout_width="wrap_content"
-        android:layout_height="fill_parent"
-        android:layout_alignParentLeft="true"
-        android:layout_marginRight="10dp" />
-    &lt;TextView android:id="@+id/title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_toRightOf="@id/image"
-        style="@style/NotificationTitle" />
-    &lt;TextView android:id="@+id/text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_toRightOf="@id/image"
-        android:layout_below="@id/title"
-        style="@style/NotificationText" />
-&lt;/RelativeLayout>
+&lt;activity
+    android:name=".MainActivity"
+    android:label="&#64;string/app_name" &gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.intent.action.MAIN" /&gt;
+        &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
+    &lt;/intent-filter&gt;
+&lt;/activity&gt;
+&lt;activity
+    android:name=".ResultActivity"
+    android:parentActivityName=".MainActivity"&gt;
+    &lt;meta-data
+        android:name="android.support.PARENT_ACTIVITY"
+        android:value=".MainActivity"/&gt;
+&lt;/activity&gt;
 </pre>
-
-    <p>Notice that the two {@link android.widget.TextView} elements include the {@code style}
-attribute. It's important that you use style resources for the text in your custom
-notifications, because the background color of the notification can vary across different
-devices and platform versions. Beginning with Android 2.3 (API level 9), the system defines a
-style for the text it uses for the default notification layouts. Thus, you should apply
-that style when running on Android 2.3 or higher to ensure that your text is visible against
-the background.</p>
-
-    <p>For example, to use the standard text colors on versions of Android lower than 2.3, you
-should use the following styles for {@code res/values/styles.xml}:</p>
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;resources>
-    &lt;style name="NotificationText">
-      &lt;item name="android:textColor">?android:attr/textColorPrimary&lt;/item>
-    &lt;/style>
-    &lt;style name="NotificationTitle">
-      &lt;item name="android:textColor">?android:attr/textColorPrimary&lt;/item>
-      &lt;item name="android:textStyle">bold&lt;/item>
-    &lt;/style>
-    &lt;!-- If you want a slightly different color for some text,
-         consider using ?android:attr/textColorSecondary -->
-&lt;/resources>
-</pre>
-    <p>Then, to apply the system's default colors for notifications on Android
-2.3 and higher, use the following styles for {@code res/values-v9/styles.xml}:</p>
-<pre>
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;resources>
-    &lt;style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
-    &lt;style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
-&lt;/resources>
-</pre>
-    <p>Now, when running on Android 2.3 (API level 9) or higher, the text in your custom view will
-use the same colors that the system does for default notifications. This is important because later
-versions of Android actually change the background color of the notifications to be dark. Inheriting
-the system's styles ensures that your text will be light in such cases, but also if the background
-is some other unexpected color, your text will also change as appropriate.</p>
-  </li>
-
-  <li>Now, in the application code, use the RemoveViews
-    methods to define the image and text. Then pass the RemoteViews object to the <var>contentView</var>
-    field of the Notification, as shown in this example:
-<pre>
-RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
-contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
-contentView.setTextViewText(R.id.title, "Custom notification");
-contentView.setTextViewText(R.id.text, "This is a custom layout");
-notification.contentView = contentView;
-</pre>
-
-    <p>As shown here, pass the application's package name and the layout
-    resource ID to the RemoteViews constructor. Then, define the content for the ImageView and TextView,
-    using the {@link android.widget.RemoteViews#setImageViewResource(int, int) setImageViewResource()}
-    and {@link android.widget.RemoteViews#setTextViewText(int, CharSequence) setTextViewText()}.
-    In each case, pass the reference ID of the appropriate View object that you want to set, along with
-    the value for that View. Finally, the RemoteViews object is passed to the Notification in the
-    <var>contentView</var> field.</p>
-  </li>
-
-  <li>Because you don't need the
-    {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-    setLatestEventInfo()} method when using a custom view, you must define the Intent for the Notification
-    with the <var>contentIntent</var> field, as in this example:
-<pre>
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-notification.contentIntent = contentIntent;
-</pre>
-  </li>
-
-  <li>The notification can now be sent as usual:
-    <pre>mNotificationManager.notify(CUSTOM_VIEW_ID, notification);</pre>
-  </li>
+    </li>
+    <li>
+        Create a back stack based on the {@link android.content.Intent} that starts the
+        {@link android.app.Activity}:
+        <ol style="list-style-type: lower-alpha;">
+            <li>
+                Create the {@link android.content.Intent} to start the {@link android.app.Activity}.
+            </li>
+            <li>
+                Create a stack builder by calling {@link android.app.TaskStackBuilder#create
+                TaskStackBuilder.create()}.
+            </li>
+            <li>
+                Add the back stack to the stack builder by calling
+                {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
+                For each {@link android.app.Activity} in the hierarchy you've defined in the
+                manifest, the back stack contains an {@link android.content.Intent} object that
+                starts the {@link android.app.Activity}. This method also adds flags that start the
+                stack in a fresh task.
+                <p class="note">
+                    <strong>Note:</strong> Although the argument to
+                    {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
+                    is a reference to the started {@link android.app.Activity}, the method call
+                    doesn't add the {@link android.content.Intent} that starts the
+                    {@link android.app.Activity}. Instead, that's taken care of in the next step.
+                </p>
+            </li>
+            <li>
+                Add the {@link android.content.Intent} that starts the {@link android.app.Activity}
+                from the notification, by calling
+                {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+                Pass the {@link android.content.Intent} you created in the first step as the
+                argument to
+                {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+            </li>
+            <li>
+                If you need to, add arguments to {@link android.content.Intent} objects on the
+                stack by calling {@link android.support.v4.app.TaskStackBuilder#editIntentAt
+                TaskStackBuilder.editIntentAt()}. This is sometimes necessary to ensure that the
+                target {@link android.app.Activity} displays meaningful data when the user navigates
+                to it using <i>Back</i>.
+            </li>
+            <li>
+                Get a {@link android.app.PendingIntent} for this back stack by calling
+                {@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
+                You can then use this {@link android.app.PendingIntent} as the argument to
+                {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+                setContentIntent()}.
+            </li>
+        </ol>
+     </li>
 </ol>
+<p>
+    The following code snippet demonstrates the process:
+</p>
+<pre>
+...
+Intent resultIntent = new Intent(this, ResultActivity.class);
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+// Gets a PendingIntent containing the entire back stack
+PendingIntent resultPendingIntent =
+        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
+...
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+builder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mNotificationManager.notify(id, builder.build());
+</pre>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ExtendedNotification">Setting up a special activity PendingIntent</h3>
+<p>
+    The following section describes how to set up a special activity
+    {@link android.app.PendingIntent}.
+</p>
+<p>
+    A special {@link android.app.Activity} doesn't need a back stack, so you don't have to
+    define its {@link android.app.Activity} hierarchy in the manifest, and you don't have
+    to call
+    {@link android.support.v4.app.TaskStackBuilder#addParentStack  addParentStack()} to build a
+    back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options,
+    and create the {@link android.app.PendingIntent} by calling
+    {@link android.app.PendingIntent#getActivity getActivity()}:
+</p>
+<ol>
+    <li>
+        In your manifest, add the following attributes to the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+        element for the {@link android.app.Activity}
+        <dl>
+            <dt>
+<code><a href="guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
+            </dt>
+            <dd>
+                The activity's fully-qualified class name.
+            </dd>
+            <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
+            </dt>
+            <dd>
+                Combined with the
+                {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag
+                that you set in code, this ensures that this {@link android.app.Activity} doesn't
+                go into the application's default task. Any existing tasks that have the
+                application's default affinity are not affected.
+            </dd>
+            <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
+            </dt>
+            <dd>
+                Excludes the new task from <i>Recents</i>, so that the user can't accidentally
+                navigate back to it.
+            </dd>
+        </dl>
+        <p>
+            This snippet shows the element:
+        </p>
+<pre>
+&lt;activity
+    android:name=".ResultActivity"
+...
+    android:launchMode="singleTask"
+    android:taskAffinity=""
+    android:excludeFromRecents="true"&gt;
+&lt;/activity&gt;
+...
+</pre>
+    </li>
+    <li>
+        Build and issue the notification:
+        <ol style="list-style-type: lower-alpha;">
+            <li>
+                Create an {@link android.content.Intent} that starts the
+                {@link android.app.Activity}.
+            </li>
+            <li>
+                Set the {@link android.app.Activity} to start in a new, empty task by calling
+                {@link android.content.Intent#setFlags setFlags()} with the flags
+                {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
+                and
+                {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
+            </li>
+            <li>
+                Set any other options you need for the {@link android.content.Intent}.
+            </li>
+            <li>
+                Create a {@link android.app.PendingIntent} from the {@link android.content.Intent}
+                by calling {@link android.app.PendingIntent#getActivity getActivity()}.
+                You can then use this {@link android.app.PendingIntent} as the argument to
+                {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+                setContentIntent()}.
+            </li>
+        </ol>
+    <p>
+        The following code snippet demonstrates the process:
+    </p>
+<pre>
+// Instantiate a Builder object.
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+// Creates an Intent for the Activity
+Intent notifyIntent =
+        new Intent(new ComponentName(this, ResultActivity.class));
+// Sets the Activity to start in a new, empty task
+notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+// Creates the PendingIntent
+PendingIntent notifyIntent =
+        PendingIntent.getActivity(
+        this,
+        0,
+        notifyIntent
+        PendingIntent.FLAG_UPDATE_CURRENT
+);
 
+// Puts the PendingIntent into the notification builder
+builder.setContentIntent(notifyIntent);
+// Notifications are issued by sending them to the
+// NotificationManager system service.
+NotificationManager mNotificationManager =
+    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Builds an anonymous Notification object from the builder, and
+// passes it to the NotificationManager
+mNotificationManager.notify(id, builder.build());
+</pre>
+    </li>
+</ol>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Progress">Displaying Progress in a Notification</h2>
+<p>
+    Notifications can include an animated progress indicator that shows users the status
+    of an ongoing operation. If you can estimate how long the operation takes and how much of it
+    is complete at any time, use the "determinate" form of the indicator
+    (a progress bar). If you can't estimate the length of the operation, use the
+    "indeterminate" form of the indicator (an activity indicator).
+</p>
+<p>
+    Progress indicators are displayed with the platform's implementation of the
+    {@link android.widget.ProgressBar} class.
+</p>
+<p>
+    To use a progress indicator, call
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. The
+    determinate and indeterminate forms are described in the following sections.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3>
+<p>
+    To display a determinate progress bar, add the bar to your notification by calling
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+    setProgress(max, progress, false)} and then issue the notification. As your operation proceeds,
+    increment <code>progress</code>, and update the notification. At the end of the operation,
+    <code>progress</code> should equal <code>max</code>. A common way to call
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
+    is to set <code>max</code> to 100 and then increment <code>progress</code> as a
+    "percent complete" value for the operation.
+</p>
+<p>
+    You can either leave the progress bar showing when the operation is done, or remove it. In
+    either case, remember to update the notification text to show that the operation is complete.
+    To remove the progress bar, call
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+    setProgress(0, 0, false)}. For example:
+</p>
+<pre>
+...
+mNotifyManager =
+        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mBuilder = new NotificationCompat.Builder(this);
+mBuilder.setContentTitle("Picture Download")
+    .setContentText("Download in progress")
+    .setSmallIcon(R.drawable.ic_notification);
+// Start a lengthy operation in a background thread
+new Thread(
+    new Runnable() {
+        &#64;Override
+        public void run() {
+            int incr;
+            // Do the "lengthy" operation 20 times
+            for (incr = 0; incr &lt;= 100; incr+=5) {
+                    // Sets the progress indicator to a max value, the
+                    // current completion percentage, and "determinate"
+                    // state
+                    mBuilder.setProgress(100, incr, false);
+                    // Displays the progress bar for the first time.
+                    mNotifyManager.notify(0, mBuilder.build());
+                        // Sleeps the thread, simulating an operation
+                        // that takes time
+                        try {
+                            // Sleep for 5 seconds
+                            Thread.sleep(5*1000);
+                        } catch (InterruptedException e) {
+                            Log.d(TAG, "sleep failure");
+                        }
+            }
+            // When the loop is finished, updates the notification
+            mBuilder.setContentText("Download complete")
+            // Removes the progress bar
+                    .setProgress(0,0,false);
+            mNotifyManager.notify(ID, mBuilder.build());
+        }
+    }
+// Starts the thread by calling the run() method in its Runnable
+).start();
+</pre>
+<p>
+    The resulting notifications are shown in figure 6. On the left side is a snapshot of the
+    notification during the operation; on the right side is a snapshot of it after the operation
+    has finished.
+</p>
+<img
+    id="figure6"
+    src="{@docRoot}images/ui/notifications/progress_bar_summary.png"
+    height="84"
+    alt="" />
+<p class="img-caption">
+<strong>Figure 6.</strong> The progress bar during and after the operation.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ActivityIndicator">Displaying a continuing activity indicator</h3>
+<p>
+    To display an indeterminate activity indicator, add it to your notification with
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
+    (the first two arguments are ignored), and issue the notification. The result is an indicator
+    that has the same style as a progress bar, except that its animation is ongoing.
+</p>
+<p>
+    Issue the notification at the beginning of the operation. The animation will run until you
+    modify your notification. When the operation is done, call
+    {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+    setProgress(0, 0, false)} and then update the notification to remove the activity indicator.
+    Always do this; otherwise, the animation will run even when the operation is complete. Also
+    remember to change the notification text to indicate that the operation is complete.
+</p>
+<p>
+    To see how activity indicators work, refer to the preceding snippet. Locate the following lines:
+</p>
+<pre>
+// Sets the progress indicator to a max value, the current completion
+// percentage, and "determinate" state
+mBuilder.setProgress(100, incr, false);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
+</pre>
+<p>
+    Replace the lines you've found with the following lines:
+</p>
+<pre>
+ // Sets an activity indicator for an operation of indeterminate length
+mBuilder.setProgress(0, 0, false);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
+</pre>
+<p>
+    The resulting indicator is shown in figure 7:
+</p>
+<img
+    id="figure7"
+    src="{@docRoot}images/ui/notifications/activity_indicator.png"
+    height="99"
+    alt="" />
+<p class="img-caption"><strong>Figure 7.</strong> An ongoing activity indicator.</p>
 
-<p>The {@link android.widget.RemoteViews} class also includes methods that you can use to easily add
-a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
-in your notification's layout. For more information about creating custom layouts for your
-notification, refer to the {@link android.widget.RemoteViews} class reference.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
 
-<p class="caution"><strong>Caution:</strong>
-When creating a custom notification layout, you must take special care to ensure that your
-custom layout functions properly in different device orientations and resolutions. While this
-advice applies to all View layouts created on Android, it is especially important in this case
-because your layout real estate is very restricted. So don't make your custom layout too
-complex and be sure to test it in various configurations.</p>
-
-
-
-
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="CustomNotification">Custom Notification Layouts</h2>
+<p>
+    The notifications framework allows you to define a custom notification layout, which
+    defines the notification's appearance in a {@link android.widget.RemoteViews} object.
+    Custom layout notifications are similar to normal notifications, but they're based on a
+    {@link android.widget.RemoteViews} defined in a XML layout file.
+</p>
+<p>
+    To define a custom notification layout, start by instantiating a
+    {@link android.widget.RemoteViews} object that inflates an XML layout file. Then,
+    instead of calling methods such as
+    {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
+    call {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. To set
+    content details in the custom notification, use the methods in
+    {@link android.widget.RemoteViews} to set the values of the view's children:
+</p>
+<ol>
+    <li>
+        Create an XML layout for the notification in a separate file. You can use any file name
+        you wish, but you must use the extension <code>.xml</code>
+    </li>
+    <li>
+        In your app, use {@link android.widget.RemoteViews} methods to define your notification's
+        icons and text. Put this {@link android.widget.RemoteViews} object into your
+        {@link android.support.v4.app.NotificationCompat.Builder} by calling
+        {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Avoid
+        setting a background {@link android.graphics.drawable.Drawable} on your
+        {@link android.widget.RemoteViews} object, because your text color may become unreadable.
+    </li>
+</ol>
+<p>
+    The {@link android.widget.RemoteViews} class also includes methods that you can use to easily
+    add a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
+    to your notification's layout. For more information about creating custom layouts for your
+    notification, refer to the {@link android.widget.RemoteViews} reference documentation.
+</p>
+<p class="caution">
+    <strong>Caution:</strong> When you use a custom notification layout, take special care to
+    ensure that your custom layout works with different device orientations and resolutions. While
+    this advice applies to all View layouts, it's especially important for notifications because
+    the space in the notification drawer is very restricted. Don't make your custom layout too
+    complex, and be sure to test it in various configurations.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h4>Using style resources for custom notification text</h4>
+<p>
+    Always use style resources for the text of a custom notification. The background color of the
+    notification can vary across different devices and platform versions, and using style resources
+    helps you account for this. Starting in API level 9, the system defined a style for the
+    standard notification layout text. If you use the same style in applications that target API
+    level 9 or higher, you'll ensure that your text is visible against the display background.
+</p>
diff --git a/docs/html/images/ui/notifications/activity_indicator.png b/docs/html/images/ui/notifications/activity_indicator.png
new file mode 100644
index 0000000..e21fae2
--- /dev/null
+++ b/docs/html/images/ui/notifications/activity_indicator.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigpicture_notification.png b/docs/html/images/ui/notifications/bigpicture_notification.png
new file mode 100644
index 0000000..ced6380
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigpicture_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigpicture_notification_callouts.png b/docs/html/images/ui/notifications/bigpicture_notification_callouts.png
new file mode 100644
index 0000000..e2d313a
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigpicture_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigtext_notification.png b/docs/html/images/ui/notifications/bigtext_notification.png
new file mode 100644
index 0000000..cd6e764
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigtext_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigtext_notification_callouts.png b/docs/html/images/ui/notifications/bigtext_notification_callouts.png
new file mode 100644
index 0000000..4cfa403
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigtext_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/custom_message.png b/docs/html/images/ui/notifications/custom_message.png
new file mode 100755
index 0000000..00b7632
--- /dev/null
+++ b/docs/html/images/ui/notifications/custom_message.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/iconic_notification.png b/docs/html/images/ui/notifications/iconic_notification.png
new file mode 100644
index 0000000..4cabfdb
--- /dev/null
+++ b/docs/html/images/ui/notifications/iconic_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/inbox_notification.png b/docs/html/images/ui/notifications/inbox_notification.png
new file mode 100644
index 0000000..fb182d5
--- /dev/null
+++ b/docs/html/images/ui/notifications/inbox_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/inbox_notification_callouts.png b/docs/html/images/ui/notifications/inbox_notification_callouts.png
new file mode 100644
index 0000000..2ec818e
--- /dev/null
+++ b/docs/html/images/ui/notifications/inbox_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/normal_notification.png b/docs/html/images/ui/notifications/normal_notification.png
new file mode 100644
index 0000000..3cf0231
--- /dev/null
+++ b/docs/html/images/ui/notifications/normal_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/normal_notification_callouts.png b/docs/html/images/ui/notifications/normal_notification_callouts.png
new file mode 100644
index 0000000..db57daf
--- /dev/null
+++ b/docs/html/images/ui/notifications/normal_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/notifications_window.png b/docs/html/images/ui/notifications/notifications_window.png
new file mode 100755
index 0000000..0354ee9
--- /dev/null
+++ b/docs/html/images/ui/notifications/notifications_window.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/progress_bar_summary.png b/docs/html/images/ui/notifications/progress_bar_summary.png
new file mode 100644
index 0000000..073e697d
--- /dev/null
+++ b/docs/html/images/ui/notifications/progress_bar_summary.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/progress_indicator_1.png b/docs/html/images/ui/notifications/progress_indicator_1.png
new file mode 100644
index 0000000..f4c2365
--- /dev/null
+++ b/docs/html/images/ui/notifications/progress_indicator_1.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/progress_indicator_2.png b/docs/html/images/ui/notifications/progress_indicator_2.png
new file mode 100644
index 0000000..975c90e
--- /dev/null
+++ b/docs/html/images/ui/notifications/progress_indicator_2.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/status_bar.png b/docs/html/images/ui/notifications/status_bar.png
new file mode 100755
index 0000000..f0240a5
--- /dev/null
+++ b/docs/html/images/ui/notifications/status_bar.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/updated_notification.png b/docs/html/images/ui/notifications/updated_notification.png
new file mode 100644
index 0000000..f69fa4b
--- /dev/null
+++ b/docs/html/images/ui/notifications/updated_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 9b1a892..1460996 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -153,9 +153,9 @@
     <skip />
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuario <xliff:g id="USER">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
-    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Celular <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Móvil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batería <xliff:g id="STATE">%s</xliff:g>"</string>
-    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo avión <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo de avión <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarma: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datos de 2G-3G inhabilitados"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 9a7e56df..9f0fbda 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -175,7 +175,7 @@
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
     <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
-    <string name="start_dreams" msgid="6170089063982549905">"Activar suspensión"</string>
+    <string name="start_dreams" msgid="6170089063982549905">"Suspender"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 58c9dec..468375f 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -203,5 +203,5 @@
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Độ sáng"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
-    <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách trượt xuống."\n"Trượt lại xuống để có các điều khiển hệ thống."</string>
+    <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống."\n"Vuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 29b682d..d0323f0 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -204,6 +204,6 @@
     <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"無線螢幕分享"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
-    <string name="status_bar_help_title" msgid="1199237744086469217">"通知會顯示在這裡"</string>
+    <string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。"\n"再次向下滑動即可使用系統控制項。"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/Somnambulator.java b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
index 9356ff2..0dd6d92 100644
--- a/packages/SystemUI/src/com/android/systemui/Somnambulator.java
+++ b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
@@ -1,4 +1,4 @@
-/*);
+/*
  * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,38 +18,23 @@
 
 import android.app.Activity;
 import android.content.Intent;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
-import android.util.Slog;
+import android.service.dreams.Sandman;
 
+/**
+ * A simple activity that launches a dream.
+ * <p>
+ * Note: This Activity is special.  If this class is moved to another package or
+ * renamed, be sure to update the component name in {@link Sandman}.
+ * </p>
+ */
 public class Somnambulator extends Activity {
-    public static final String TAG = "Somnambulator";
-
-    public static final int DEFAULT_SCREENSAVER_ENABLED = 1;
-    public static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
-
     public Somnambulator() {
     }
 
-    private boolean isScreenSaverEnabled() {
-        return Settings.Secure.getIntForUser(getContentResolver(),
-                Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
-                UserHandle.USER_CURRENT) != 0;
-    }
-
-    private boolean isScreenSaverActivatedOnDock() {
-        return Settings.Secure.getIntForUser(getContentResolver(),
-                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
-                DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
-    }
-
     @Override
     public void onStart() {
         super.onStart();
+
         final Intent launchIntent = getIntent();
         final String action = launchIntent.getAction();
         if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
@@ -64,23 +49,12 @@
             setResult(RESULT_OK, resultIntent);
         } else {
             boolean docked = launchIntent.hasCategory(Intent.CATEGORY_DESK_DOCK);
-
-            if (docked && !(isScreenSaverEnabled() && isScreenSaverActivatedOnDock())) {
-                Slog.i(TAG, "Dreams currently disabled for docks.");
+            if (docked) {
+                Sandman.startDreamWhenDockedIfAppropriate(this);
             } else {
-                IDreamManager somnambulist = IDreamManager.Stub.asInterface(
-                        ServiceManager.checkService(DreamService.DREAM_SERVICE));
-                if (somnambulist != null) {
-                    try {
-                        Slog.v(TAG, "Dreaming on " + (docked ? "dock insertion" : "user request"));
-                        somnambulist.dream();
-                    } catch (RemoteException e) {
-                        // fine, stay asleep then
-                    }
-                }
+                Sandman.startDreamByUserRequest(this);
             }
         }
         finish();
     }
-
 }
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 2d4eb79..0e456f1 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -37,11 +37,9 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
+import android.service.dreams.Sandman;
 import android.util.Slog;
 
 import java.io.FileDescriptor;
@@ -59,9 +57,6 @@
     private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
     private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
 
-    private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
-    private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
-
     private final Context mContext;
     private final TwilightService mTwilightService;
     private final Handler mHandler = new Handler();
@@ -496,18 +491,20 @@
             // activity manager take care of both the start and config
             // change.
             Intent homeIntent = buildHomeIntent(category);
-            try {
-                int result = ActivityManagerNative.getDefault().startActivityWithConfig(
-                        null, homeIntent, null, null, null, 0, 0,
-                        mConfiguration, null, UserHandle.USER_CURRENT);
-                if (result >= ActivityManager.START_SUCCESS) {
-                    dockAppStarted = true;
-                } else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
-                    Slog.e(TAG, "Could not start dock app: " + homeIntent
-                            + ", startActivityWithConfig result " + result);
+            if (Sandman.shouldStartDockApp(mContext, homeIntent)) {
+                try {
+                    int result = ActivityManagerNative.getDefault().startActivityWithConfig(
+                            null, homeIntent, null, null, null, 0, 0,
+                            mConfiguration, null, UserHandle.USER_CURRENT);
+                    if (result >= ActivityManager.START_SUCCESS) {
+                        dockAppStarted = true;
+                    } else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
+                        Slog.e(TAG, "Could not start dock app: " + homeIntent
+                                + ", startActivityWithConfig result " + result);
+                    }
+                } catch (RemoteException ex) {
+                    Slog.e(TAG, "Could not start dock app: " + homeIntent, ex);
                 }
-            } catch (RemoteException ex) {
-                Slog.e(TAG, "Could not start dock app: " + homeIntent, ex);
             }
         }
 
@@ -515,41 +512,11 @@
         sendConfigurationLocked();
 
         // If we did not start a dock app, then start dreaming if supported.
-        if (category != null && !dockAppStarted
-                && isScreenSaverEnabledLocked() && isScreenSaverActivatedOnDockLocked()) {
-            Slog.i(TAG, "Activating dream while docked.");
-            try {
-                IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
-                        ServiceManager.getService(DreamService.DREAM_SERVICE));
-                if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
-                    // Wake up.
-                    // The power manager will wake up the system when it starts receiving power
-                    // but there is a race between that happening and the UI mode manager
-                    // starting a dream.  We want the system to already be awake
-                    // by the time this happens.  Otherwise the dream may not start.
-                    mPowerManager.wakeUp(SystemClock.uptimeMillis());
-
-                    // Dream.
-                    dreamManagerService.dream();
-                }
-            } catch (RemoteException ex) {
-                Slog.e(TAG, "Could not start dream when docked.", ex);
-            }
+        if (category != null && !dockAppStarted) {
+            Sandman.startDreamWhenDockedIfAppropriate(mContext);
         }
     }
 
-    private boolean isScreenSaverEnabledLocked() {
-        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
-                UserHandle.USER_CURRENT) != 0;
-    }
-
-    private boolean isScreenSaverActivatedOnDockLocked() {
-        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
-                DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
-    }
-
     private void adjustStatusBarCarModeLocked() {
         if (mStatusBarManager == null) {
             mStatusBarManager = (StatusBarManager)
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index b8d7286..f59e30d 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1835,7 +1835,8 @@
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
                 // Note: isEnabledLP() does not apply here - always return info
-                return PackageParser.generateApplicationInfo(p, flags, ps.readUserState(userId));
+                return PackageParser.generateApplicationInfo(
+                        p, flags, ps.readUserState(userId), userId);
             }
             if ("android".equals(packageName)||"system".equals(packageName)) {
                 return mAndroidApplication;
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
index bd56d62..f0a2b92 100644
--- a/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
+++ b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
@@ -54,6 +54,10 @@
                 android:id="@+id/filterselection"
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
             <TextView
                 android:id="@+id/slider1Text"
                 android:layout_width="match_parent"
@@ -124,6 +128,11 @@
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
             </LinearLayout>
     </ScrollView>
 </LinearLayout>
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
index cc5cc4d..a7dd165 100644
--- a/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
+++ b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
@@ -29,5 +29,6 @@
     <string name="gamma">Gamma</string>
     <string name="saturation">Saturation</string>
     <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
 
 </resources>
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..ac02101
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012 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.rs.image2;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+    private ScriptIntrinsicBlend mBlend;
+    private ScriptC_blend mBlendHelper;
+    private short image1Alpha = 128;
+    private short image2Alpha = 128;
+
+    String mIntrinsicNames[];
+
+    private Allocation image1;
+    private Allocation image2;
+    private int currentIntrinsic = 0;
+
+    private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    currentIntrinsic = pos;
+                    runTest();
+                    act.updateDisplay();
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    public void createTest(android.content.res.Resources res) {
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+        mBlendHelper = new ScriptC_blend(mRS);
+        mBlendHelper.set_alpha((short)128);
+
+        image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+        mIntrinsicNames = new String[14];
+        mIntrinsicNames[0] = "Source";
+        mIntrinsicNames[1] = "Destination";
+        mIntrinsicNames[2] = "Source Over";
+        mIntrinsicNames[3] = "Destination Over";
+        mIntrinsicNames[4] = "Source In";
+        mIntrinsicNames[5] = "Destination In";
+        mIntrinsicNames[6] = "Source Out";
+        mIntrinsicNames[7] = "Destination Out";
+        mIntrinsicNames[8] = "Source Atop";
+        mIntrinsicNames[9] = "Destination Atop";
+        mIntrinsicNames[10] = "XOR";
+        mIntrinsicNames[11] = "Add";
+        mIntrinsicNames[12] = "Subtract";
+        mIntrinsicNames[13] = "Multiply";
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setAdapter(new ArrayAdapter<String>(
+            act, R.layout.spinner_layout, mIntrinsicNames));
+        s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+        return true;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Image 1 Alpha");
+        b.setMax(255);
+        b.setProgress(image1Alpha);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        image1Alpha = (short)progress;
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Image 2 Alpha");
+        b.setMax(255);
+        b.setProgress(image2Alpha);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        image2Alpha = (short)progress;
+    }
+
+    public void runTest() {
+        image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+        image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+        mBlendHelper.set_alpha(image1Alpha);
+        mBlendHelper.forEach_setImageAlpha(image1);
+
+        mBlendHelper.set_alpha(image2Alpha);
+        mBlendHelper.forEach_setImageAlpha(image2);
+
+        switch (currentIntrinsic) {
+        case 0:
+            mBlend.forEachSrc(image1, image2);
+            break;
+        case 1:
+            mBlend.forEachDst(image1, image2);
+            break;
+        case 2:
+            mBlend.forEachSrcOver(image1, image2);
+            break;
+        case 3:
+            mBlend.forEachDstOver(image1, image2);
+            break;
+        case 4:
+            mBlend.forEachSrcIn(image1, image2);
+            break;
+        case 5:
+            mBlend.forEachDstIn(image1, image2);
+            break;
+        case 6:
+            mBlend.forEachSrcOut(image1, image2);
+            break;
+        case 7:
+            mBlend.forEachDstOut(image1, image2);
+            break;
+        case 8:
+            mBlend.forEachSrcAtop(image1, image2);
+            break;
+        case 9:
+            mBlend.forEachDstAtop(image1, image2);
+            break;
+        case 10:
+            mBlend.forEachXor(image1, image2);
+            break;
+        case 11:
+            mBlend.forEachAdd(image1, image2);
+            break;
+        case 12:
+            mBlend.forEachSubtract(image1, image2);
+            break;
+        case 13:
+            mBlend.forEachMultiply(image1, image2);
+            break;
+        }
+
+        mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
index be87716..b518b02 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
@@ -24,37 +24,38 @@
 import android.widget.TextView;
 
 public class Blur25 extends TestBase {
+    private boolean mUseIntrinsic = false;
+    private ScriptIntrinsicBlur mIntrinsic;
+
     private int MAX_RADIUS = 25;
     private ScriptC_threshold mScript;
-    private ScriptC_vertical_blur mScriptVBlur;
-    private ScriptC_horizontal_blur mScriptHBlur;
-    private int mRadius = MAX_RADIUS;
+    private float mRadius = MAX_RADIUS;
     private float mSaturation = 1.0f;
     private Allocation mScratchPixelsAllocation1;
     private Allocation mScratchPixelsAllocation2;
 
 
+    public Blur25(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
     public boolean onBar1Setup(SeekBar b, TextView t) {
         t.setText("Radius");
         b.setProgress(100);
         return true;
     }
-    public boolean onBar2Setup(SeekBar b, TextView t) {
-        b.setProgress(50);
-        t.setText("Saturation");
-        return true;
-    }
 
 
     public void onBar1Changed(int progress) {
-        float fRadius = progress / 100.0f;
-        fRadius *= (float)(MAX_RADIUS);
-        mRadius = (int)fRadius;
-        mScript.set_radius(mRadius);
-    }
-    public void onBar2Changed(int progress) {
-        mSaturation = (float)progress / 50.0f;
-        mScriptVBlur.invoke_setSaturation(mSaturation);
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
     }
 
 
@@ -62,40 +63,52 @@
         int width = mInPixelsAllocation.getType().getX();
         int height = mInPixelsAllocation.getType().getY();
 
-        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
-        tb.setX(width);
-        tb.setY(height);
-        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
-        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setRadius(MAX_RADIUS);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
 
-        mScriptVBlur = new ScriptC_vertical_blur(mRS, res, R.raw.vertical_blur);
-        mScriptHBlur = new ScriptC_horizontal_blur(mRS, res, R.raw.horizontal_blur);
+            Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+            tb.setX(width);
+            tb.setY(height);
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+            mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
 
-        mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
-        mScript.set_width(width);
-        mScript.set_height(height);
-        mScript.set_radius(mRadius);
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.invoke_setRadius(MAX_RADIUS);
 
-        mScriptVBlur.invoke_setSaturation(mSaturation);
-
-        mScript.bind_InPixel(mInPixelsAllocation);
-        mScript.bind_OutPixel(mOutPixelsAllocation);
-        mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
-        mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
-
-        mScript.set_vBlurScript(mScriptVBlur);
-        mScript.set_hBlurScript(mScriptHBlur);
+            mScript.set_InPixel(mInPixelsAllocation);
+            mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+            mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+        }
     }
 
     public void runTest() {
-        mScript.invoke_filter();
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+            mScript.forEach_horz(mScratchPixelsAllocation2);
+            mScript.forEach_vert(mOutPixelsAllocation);
+        }
     }
 
     public void setupBenchmark() {
-        mScript.set_radius(MAX_RADIUS);
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.invoke_setRadius(MAX_RADIUS);
+        }
     }
 
     public void exitBenchmark() {
-        mScript.set_radius(mRadius);
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
     }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..3b0f86a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private ScriptIntrinsicColorMatrix mIntrinsic;
+    private boolean mUseIntrinsic;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+        mUseIntrinsic = useIntrinsic;
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+            if (mUseGrey) {
+                mIntrinsic.setGreyscale();
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..7635e13
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve3x3(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..d2da3c4
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+    private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve5x5(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..ef71907
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..96787d7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+
+    public void createTest(android.content.res.Resources res) {
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
index 995cf9d..97beb88 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
@@ -23,12 +23,16 @@
 public class Fisheye extends TestBase {
     private ScriptC_fisheye_full mScript_full = null;
     private ScriptC_fisheye_relaxed mScript_relaxed = null;
+    private ScriptC_fisheye_approx_full mScript_approx_full = null;
+    private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
     private final boolean relaxed;
     private float center_x = 0.5f;
     private float center_y = 0.5f;
     private float scale = 0.5f;
 
-    public Fisheye(boolean relaxed) {
+    public Fisheye(boolean approx, boolean relaxed) {
+        this.approx = approx;
         this.relaxed = relaxed;
     }
 
@@ -65,7 +69,18 @@
     }
 
     private void do_init() {
-        if (relaxed)
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+            else
+                mScript_approx_full.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+        } else if (relaxed)
             mScript_relaxed.invoke_init_filter(
                     mInPixelsAllocation.getType().getX(),
                     mInPixelsAllocation.getType().getY(), center_x, center_y,
@@ -78,7 +93,19 @@
     }
 
     public void createTest(android.content.res.Resources res) {
-        if (relaxed) {
+        if (approx) {
+            if (relaxed) {
+                mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+                        res, R.raw.fisheye_approx_relaxed);
+                mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            } else {
+                mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+                        R.raw.fisheye_approx_full);
+                mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            }
+        } else if (relaxed) {
             mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
                     R.raw.fisheye_relaxed);
             mScript_relaxed.set_in_alloc(mInPixelsAllocation);
@@ -93,7 +120,12 @@
     }
 
     public void runTest() {
-        if (relaxed)
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mOutPixelsAllocation);
+        } else if (relaxed)
             mScript_relaxed.forEach_root(mOutPixelsAllocation);
         else
             mScript_full.forEach_root(mOutPixelsAllocation);
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
index e00edd7..dfd3c32 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
@@ -40,19 +40,40 @@
         mScript.set_gNoiseStrength(s);
     }
 
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
     public void createTest(android.content.res.Resources res) {
         int width = mInPixelsAllocation.getType().getX();
         int height = mInPixelsAllocation.getType().getY();
 
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
         Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
-        tb.setX(width);
-        tb.setY(height);
+        tb.setX(noiseW);
+        tb.setY(noiseH);
         mNoise = Allocation.createTyped(mRS, tb.create());
         mNoise2 = Allocation.createTyped(mRS, tb.create());
 
         mScript = new ScriptC_grain(mRS, res, R.raw.grain);
-        mScript.set_gWidth(width);
-        mScript.set_gHeight(height);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
         mScript.set_gNoiseStrength(0.5f);
         mScript.set_gBlendSource(mNoise);
         mScript.set_gNoise(mNoise2);
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
index b9fbb59..a7ceebee 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
@@ -22,8 +22,8 @@
 import android.util.Log;
 
 public class GroupTest extends TestBase {
-    private ScriptC_convolve3x3 mConvolve;
-    private ScriptC_colormatrix mMatrix;
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
 
     private Allocation mScratchPixelsAllocation1;
     private ScriptGroup mGroup;
@@ -41,20 +41,20 @@
         mWidth = mInPixelsAllocation.getType().getX();
         mHeight = mInPixelsAllocation.getType().getY();
 
-        mConvolve = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
-        mMatrix = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
 
         float f[] = new float[9];
         f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
         f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
         f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
-        mConvolve.set_gCoeffs(f);
+        mConvolve.setCoefficients(f);
 
         Matrix4f m = new Matrix4f();
         m.set(1, 0, 0.2f);
         m.set(1, 1, 0.9f);
         m.set(1, 2, 0.2f);
-        mMatrix.invoke_setMatrix(m);
+        mMatrix.setColorMatrix(m);
 
         Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
         tb.setX(mWidth);
@@ -63,24 +63,23 @@
 
         if (mUseNative) {
             ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
-            b.addConnection(connect, mConvolve, mMatrix, null);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
             mGroup = b.create();
-
         } else {
             mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
         }
     }
 
     public void runTest() {
-        mConvolve.set_gIn(mInPixelsAllocation);
-        mConvolve.set_gWidth(mWidth);
-        mConvolve.set_gHeight(mHeight);
+        mConvolve.setInput(mInPixelsAllocation);
         if (mUseNative) {
-            mGroup.setOutput(mMatrix, mOutPixelsAllocation);
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
             mGroup.execute();
         } else {
-            mConvolve.forEach_root(mScratchPixelsAllocation1);
-            mMatrix.forEach_root(mScratchPixelsAllocation1, mOutPixelsAllocation);
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
         }
     }
 
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
index 9b36da14..227518f 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -34,13 +34,27 @@
 import android.util.Log;
 import java.lang.Math;
 
+import android.os.Environment;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
 public class ImageProcessingActivity2 extends Activity
                                        implements SeekBar.OnSeekBarChangeListener {
     private final String TAG = "Img";
+    private final String RESULT_FILE = "image_processing_result.csv";
+
     Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
     Bitmap mBitmapOut;
     String mTestNames[];
 
+    private Spinner mSpinner;
     private SeekBar mBar1;
     private SeekBar mBar2;
     private SeekBar mBar3;
@@ -64,6 +78,10 @@
 
     private TestBase mTest;
 
+    public void updateDisplay() {
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
+    }
 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         if (fromUser) {
@@ -81,8 +99,7 @@
             }
 
             mTest.runTest();
-            mTest.updateBitmap(mBitmapOut);
-            mDisplayView.invalidate();
+            updateDisplay();
         }
     }
 
@@ -93,6 +110,9 @@
     }
 
     void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
         mBar1.setVisibility(View.VISIBLE);
         mText1.setVisibility(View.VISIBLE);
         mTest.onBar1Setup(mBar1, mText1);
@@ -116,6 +136,9 @@
 
 
     void changeTest(int testID) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
         switch(testID) {
         case 0:
             mTest = new LevelsV4(false, false);
@@ -130,58 +153,122 @@
             mTest = new LevelsV4(true, true);
             break;
         case 4:
-            mTest = new Blur25();
+            mTest = new Blur25(false);
             break;
         case 5:
-            mTest = new Greyscale();
+            mTest = new Blur25(true);
             break;
         case 6:
-            mTest = new Grain();
+            mTest = new Greyscale();
             break;
         case 7:
-            mTest = new Fisheye(false);
+            mTest = new Grain();
             break;
         case 8:
-            mTest = new Fisheye(true);
+            mTest = new Fisheye(false, false);
             break;
         case 9:
-            mTest = new Vignette(false);
+            mTest = new Fisheye(false, true);
             break;
         case 10:
-            mTest = new Vignette(true);
+            mTest = new Fisheye(true, false);
             break;
         case 11:
-            mTest = new GroupTest(false);
+            mTest = new Fisheye(true, true);
             break;
         case 12:
+            mTest = new Vignette(false, false);
+            break;
+        case 13:
+            mTest = new Vignette(false, true);
+            break;
+        case 14:
+            mTest = new Vignette(true, false);
+            break;
+        case 15:
+            mTest = new Vignette(true, true);
+            break;
+        case 16:
+            mTest = new GroupTest(false);
+            break;
+        case 17:
             mTest = new GroupTest(true);
             break;
+        case 18:
+            mTest = new Convolve3x3(false);
+            break;
+        case 19:
+            mTest = new Convolve3x3(true);
+            break;
+        case 20:
+            mTest = new ColorMatrix(false, false);
+            break;
+        case 21:
+            mTest = new ColorMatrix(true, false);
+            break;
+        case 22:
+            mTest = new ColorMatrix(true, true);
+            break;
+        case 23:
+            mTest = new Copy();
+            break;
+        case 24:
+            mTest = new CrossProcess();
+            break;
+        case 25:
+            mTest = new Convolve5x5(false);
+            break;
+        case 26:
+            mTest = new Convolve5x5(true);
+            break;
+        case 27:
+            mTest = new Mandelbrot();
+            break;
+        case 28:
+            mTest = new Blend();
+            break;
         }
 
-        mTest.createBaseTest(this, mBitmapIn);
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
         setupBars();
 
         mTest.runTest();
-        mTest.updateBitmap(mBitmapOut);
-        mDisplayView.invalidate();
+        updateDisplay();
         mBenchmarkResult.setText("Result: not run");
     }
 
     void setupTests() {
-        mTestNames = new String[13];
+        mTestNames = new String[29];
         mTestNames[0] = "Levels Vec3 Relaxed";
         mTestNames[1] = "Levels Vec4 Relaxed";
         mTestNames[2] = "Levels Vec3 Full";
         mTestNames[3] = "Levels Vec4 Full";
         mTestNames[4] = "Blur radius 25";
-        mTestNames[5] = "Greyscale";
-        mTestNames[6] = "Grain";
-        mTestNames[7] = "Fisheye Full";
-        mTestNames[8] = "Fisheye Relaxed";
-        mTestNames[9] = "Vignette Full";
-        mTestNames[10] = "Vignette Relaxed";
-        mTestNames[11] = "Group Test (emulated)";
-        mTestNames[12] = "Group Test (native)";
+        mTestNames[5] = "Intrinsic Blur radius 25";
+        mTestNames[6] = "Greyscale";
+        mTestNames[7] = "Grain";
+        mTestNames[8] = "Fisheye Full";
+        mTestNames[9] = "Fisheye Relaxed";
+        mTestNames[10] = "Fisheye Approximate Full";
+        mTestNames[11] = "Fisheye Approximate Relaxed";
+        mTestNames[12] = "Vignette Full";
+        mTestNames[13] = "Vignette Relaxed";
+        mTestNames[14] = "Vignette Approximate Full";
+        mTestNames[15] = "Vignette Approximate Relaxed";
+        mTestNames[16] = "Group Test (emulated)";
+        mTestNames[17] = "Group Test (native)";
+        mTestNames[18] = "Convolve 3x3";
+        mTestNames[19] = "Intrinsics Convolve 3x3";
+        mTestNames[20] = "ColorMatrix";
+        mTestNames[21] = "Intrinsics ColorMatrix";
+        mTestNames[22] = "Intrinsics ColorMatrix Grey";
+        mTestNames[23] = "Copy";
+        mTestNames[24] = "CrossProcess (using LUT)";
+        mTestNames[25] = "Convolve 5x5";
+        mTestNames[26] = "Intrinsics Convolve 5x5";
+        mTestNames[27] = "Mandelbrot";
+        mTestNames[28] = "Intrinsics Blend";
+
         mTestSpinner.setAdapter(new ArrayAdapter<String>(
             this, R.layout.spinner_layout, mTestNames));
     }
@@ -202,14 +289,17 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
 
-        mBitmapIn = loadBitmap(R.drawable.city);
-        mBitmapOut = loadBitmap(R.drawable.city);
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = loadBitmap(R.drawable.img1600x1067);
 
         mSurfaceView = (SurfaceView) findViewById(R.id.surface);
 
         mDisplayView = (ImageView) findViewById(R.id.display);
         mDisplayView.setImageBitmap(mBitmapOut);
 
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
+
         mBar1 = (SeekBar) findViewById(R.id.slider1);
         mBar2 = (SeekBar) findViewById(R.id.slider2);
         mBar3 = (SeekBar) findViewById(R.id.slider3);
@@ -255,37 +345,69 @@
 
     // button hook
     public void benchmark(View v) {
-        long t = getBenchmark();
+        float t = getBenchmark();
         //long javaTime = javaFilter();
         //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
         mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        //resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (int i = 0; i < mTestNames.length; i++ ) {
+                changeTest(i);
+                float t = getBenchmark();
+                String s = new String("" + mTestNames[i] + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(0);
     }
 
     // For benchmark test
-    public long getBenchmark() {
+    public float getBenchmark() {
         mDoingBenchmark = true;
 
         mTest.setupBenchmark();
         long result = 0;
 
-        Log.v(TAG, "Warming");
-        long t = java.lang.System.currentTimeMillis() + 2000;
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
         do {
             mTest.runTest();
             mTest.finish();
         } while (t > java.lang.System.currentTimeMillis());
 
 
-        Log.v(TAG, "Benchmarking");
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
         t = java.lang.System.currentTimeMillis();
-        mTest.runTest();
-        mTest.finish();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
         t = java.lang.System.currentTimeMillis() - t;
+        float ft = (float)t;
+        ft /= ct;
 
-        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
         mTest.exitBenchmark();
         mDoingBenchmark = false;
 
-        return t;
+        return ft;
     }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..556d797
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 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.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
index 35170af..9df2eff 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -31,14 +31,18 @@
 import android.view.View;
 import android.util.Log;
 import java.lang.Math;
+import android.widget.Spinner;
 
 public class TestBase  {
     protected final String TAG = "Img";
 
     protected RenderScript mRS;
     protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
     protected Allocation mOutPixelsAllocation;
 
+    protected ImageProcessingActivity2 act;
+
     // Override to use UI elements
     public void onBar1Changed(int progress) {
     }
@@ -79,11 +83,20 @@
         return false;
     }
 
-    public final void createBaseTest(ImageProcessingActivity2 act, Bitmap b) {
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2) {
+        act = ipact;
         mRS = RenderScript.create(act);
         mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
                                                           Allocation.MipmapControl.MIPMAP_NONE,
                                                           Allocation.USAGE_SCRIPT);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
         mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
                                                            Allocation.MipmapControl.MIPMAP_NONE,
                                                            Allocation.USAGE_SCRIPT);
@@ -103,6 +116,10 @@
         mRS.finish();
     }
 
+    public void destroy() {
+        mRS.destroy();
+    }
+
     public void updateBitmap(Bitmap b) {
         mOutPixelsAllocation.copyTo(b);
     }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
index fc69eba..8618d5a 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -23,6 +23,9 @@
 public class Vignette extends TestBase {
     private ScriptC_vignette_full mScript_full = null;
     private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private ScriptC_vignette_approx_full mScript_approx_full = null;
+    private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
     private final boolean relaxed;
     private float center_x = 0.5f;
     private float center_y = 0.5f;
@@ -30,7 +33,8 @@
     private float shade = 0.5f;
     private float slope = 20.0f;
 
-    public Vignette(boolean relaxed) {
+    public Vignette(boolean approx, boolean relaxed) {
+        this.approx = approx;
         this.relaxed = relaxed;
     }
 
@@ -87,7 +91,18 @@
     }
 
     private void do_init() {
-        if (relaxed)
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+            else
+                mScript_approx_full.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+        } else if (relaxed)
             mScript_relaxed.invoke_init_vignette(
                     mInPixelsAllocation.getType().getX(),
                     mInPixelsAllocation.getType().getY(), center_x, center_y,
@@ -100,21 +115,36 @@
     }
 
     public void createTest(android.content.res.Resources res) {
-        if (relaxed) {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+                        mRS, res, R.raw.vignette_approx_relaxed);
+            else
+                mScript_approx_full = new ScriptC_vignette_approx_full(
+                        mRS, res, R.raw.vignette_approx_full);
+        } else if (relaxed)
             mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
                     R.raw.vignette_relaxed);
-        } else {
+        else
             mScript_full = new ScriptC_vignette_full(mRS, res,
                     R.raw.vignette_full);
-        }
         do_init();
     }
 
     public void runTest() {
-        if (relaxed)
-            mScript_relaxed.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
         else
-            mScript_full.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
     }
 
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..4d90725
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
@@ -0,0 +1,24 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+  v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+  v_out->a = alpha;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
new file mode 100644
index 0000000..b110b88
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    *out = convert_uchar4(p0);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
new file mode 100644
index 0000000..31e4241
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+void root(const uchar4 *v_in, uchar4 *v_out) {
+    *v_out = *v_in;
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
index 4dcfc1d..3809912 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
@@ -17,46 +17,41 @@
 rs_allocation in_alloc;
 rs_sampler sampler;
 
-static float2 center, dimensions;
-static float2 scale;
-static float alpha;
-static float radius2;
-static float factor;
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
 
-void init_filter(uint32_t dim_x, uint32_t dim_y, float focus_x, float focus_y, float k) {
-    center.x = focus_x;
-    center.y = focus_y;
-    dimensions.x = (float)dim_x;
-    dimensions.y = (float)dim_y;
-
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
     alpha = k * 2.0 + 0.75;
-    float bound2 = 0.25;
-    if (dim_x > dim_y) {
-        scale.x = 1.0;
-        scale.y = dimensions.y / dimensions.x;
-        bound2 *= (scale.y*scale.y + 1);
-    } else {
-        scale.x = dimensions.x / dimensions.y;
-        scale.y = 1.0;
-        bound2 *= (scale.x*scale.x + 1);
-    }
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+    
+    const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
     const float bound = sqrt(bound2);
     const float radius = 1.15 * bound;
     radius2 = radius*radius;
-    const float max_radian = 0.5f * M_PI - atan(alpha / bound * sqrt(radius2 - bound2));
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
     factor = bound / max_radian;
 }
 
 void root(uchar4 *out, uint32_t x, uint32_t y) {
     // Convert x and y to floating point coordinates with center as origin
-    float2 coord;
-    coord.x = (float)x / dimensions.x;
-    coord.y = (float)y / dimensions.y;
-    coord -= center;
-    const float dist = length(scale * coord);
-    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist * dist)) / dist);
-    const float scalar = radian * factor / dist;
-    const float2 new_coord = coord * scalar + center;
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
     const float4 fout = rsSample(in_alloc, sampler, new_coord);
     *out = rsPackColorTo8888(fout);
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..08b4126
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0 + 0.75;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15 * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = half_rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    *out = rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..cce42f9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
new file mode 100644
index 0000000..64d27ed
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
index 75f4021..44320a5 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
@@ -38,25 +38,25 @@
  *  1  2  1
  */
 
-int32_t gWidth;
-int32_t gHeight;
+int32_t gWMask;
+int32_t gHMask;
 
 rs_allocation gBlendSource;
 void blend9(uchar *out, uint32_t x, uint32_t y) {
-    uint32_t x1 = min(x+1, (uint32_t)gWidth);
-    uint32_t x2 = max(x-1, (uint32_t)0);
-    uint32_t y1 = min(y+1, (uint32_t)gHeight);
-    uint32_t y2 = max(y-1, (uint32_t)0);
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
 
-    uint p00 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
-    uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
-    uint p02 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
-    uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
-    uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
-    uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
-    uint p20 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
-    uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
-    uint p22 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
 
     p00 += p01;
     p02 += p10;
@@ -69,7 +69,8 @@
     p20 += p22;
     p20 += p02;
 
-    *out = (uchar)(p20 >> 10);
+    p20 = min(p20 >> 10, (uint)255);
+    *out = (uchar)p20;
 }
 
 float gNoiseStrength;
@@ -77,7 +78,7 @@
 rs_allocation gNoise;
 void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
     float4 ip = convert_float4(*in);
-    float pnoise = (float) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
 
     float energy_level = ip.r + ip.g + ip.b;
     float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
deleted file mode 100644
index ee83496..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-void root(float4 *out, const void *usrData, uint32_t x, uint32_t y) {
-    const FilterStruct *fs = (const FilterStruct *)usrData;
-    float3 blurredPixel = 0;
-    const float *gPtr = fs->gaussian;
-    if ((x > fs->radius) && (x < (fs->width - fs->radius))) {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x + r, y);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    } else {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            // Stepping left and right away from the pixel
-            int validX = rsClamp((int)x + r, (int)0, (int)(fs->width - 1));
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, validX, y);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    }
-
-    out->xyz = blurredPixel;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
deleted file mode 100644
index 0cdf9e1..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma rs java_package_name(com.android.rs.image2)
-
-#define MAX_RADIUS 25
-
-typedef struct FilterStruct_s {
-    rs_allocation ain;
-
-    float *gaussian; //[MAX_RADIUS * 2 + 1];
-    int height;
-    int width;
-    int radius;
-
-} FilterStruct;
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..55e5304
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,56 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+void root(uchar4 *v_out, uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    *v_out = (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.;
+    if (iter <= (gMaxIteration / 3))
+      *v_out = (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      *v_out = (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                        (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      *v_out = (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                        (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
index 77cd5be..9ef4898 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
@@ -1,26 +1,23 @@
 #pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
 
-#include "ip.rsh"
 
 int height;
 int width;
-int radius;
+static int radius;
 
-uchar4 * InPixel;
-uchar4 * OutPixel;
-float4 * ScratchPixel1;
-float4 * ScratchPixel2;
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
 
-rs_script vBlurScript;
-rs_script hBlurScript;
-
-const int CMD_FINISHED = 1;
+const int MAX_RADIUS = 25;
 
 // Store our coefficients here
 static float gaussian[MAX_RADIUS * 2 + 1];
 
-
-static void computeGaussianWeights() {
+void setRadius(int rad) {
+    radius = rad;
     // Compute gaussian weights for the blur
     // e is the euler's number
     float e = 2.718281828459045f;
@@ -45,8 +42,7 @@
 
     float normalizeFactor = 0.0f;
     float floatR = 0.0f;
-    int r;
-    for (r = -radius; r <= radius; r ++) {
+    for (int r = -radius; r <= radius; r ++) {
         floatR = (float)r;
         gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
         normalizeFactor += gaussian[r + radius];
@@ -54,40 +50,57 @@
 
     //Now we need to normalize the weights because all our coefficients need to add up to one
     normalizeFactor = 1.0f / normalizeFactor;
-    for (r = -radius; r <= radius; r ++) {
+    for (int r = -radius; r <= radius; r ++) {
         floatR = (float)r;
         gaussian[r + radius] *= normalizeFactor;
     }
 }
 
-
-static void copyInput() {
-    rs_allocation ain;
-    ain = rsGetAllocation(InPixel);
-    uint32_t dimx = rsAllocationGetDimX(ain);
-    uint32_t dimy = rsAllocationGetDimY(ain);
-    for (uint32_t y = 0; y < dimy; y++) {
-        for (uint32_t x = 0; x < dimx; x++) {
-            ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]);
-        }
-    }
+void copyIn(const uchar4 *in, float4 *out) {
+    *out = convert_float4(*in);
 }
 
-void filter() {
-    copyInput();
-    computeGaussianWeights();
+void vert(uchar4 *out, uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    const float *gPtr = gaussian;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, y + r);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, validH);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    }
 
-    FilterStruct fs;
-    fs.gaussian = gaussian;
-    fs.width = width;
-    fs.height = height;
-    fs.radius = radius;
+    out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out->w = 0xff;
+}
 
-    fs.ain = rsGetAllocation(ScratchPixel1);
-    rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs));
+void horz(float4 *out, uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    const float *gPtr = gaussian;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, x + r, y);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            // Stepping left and right away from the pixel
+            int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, validX, y);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    }
 
-    fs.ain = rsGetAllocation(ScratchPixel2);
-    rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
-    //rsSendToClientBlocking(CMD_FINISHED);
+    out->xyz = blurredPixel;
 }
 
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
deleted file mode 100644
index 60fd71b..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-static float saturation;
-static rs_matrix3x3 colorMat;
-
-void setSaturation(float sat) {
-    saturation = sat;
-
-    // Saturation
-    // Linear weights
-    //float rWeight = 0.3086f;
-    //float gWeight = 0.6094f;
-    //float bWeight = 0.0820f;
-
-    // Gamma 2.2 weights (we haven't converted our image to linear space yet for perf reasons)
-    float rWeight = 0.299f;
-    float gWeight = 0.587f;
-    float bWeight = 0.114f;
-
-    float oneMinusS = 1.0f - saturation;
-    rsMatrixSet(&colorMat, 0, 0, oneMinusS * rWeight + saturation);
-    rsMatrixSet(&colorMat, 0, 1, oneMinusS * rWeight);
-    rsMatrixSet(&colorMat, 0, 2, oneMinusS * rWeight);
-    rsMatrixSet(&colorMat, 1, 0, oneMinusS * gWeight);
-    rsMatrixSet(&colorMat, 1, 1, oneMinusS * gWeight + saturation);
-    rsMatrixSet(&colorMat, 1, 2, oneMinusS * gWeight);
-    rsMatrixSet(&colorMat, 2, 0, oneMinusS * bWeight);
-    rsMatrixSet(&colorMat, 2, 1, oneMinusS * bWeight);
-    rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation);
-}
-
-void root(uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
-    const FilterStruct *fs = (const FilterStruct *)usrData;
-    float3 blurredPixel = 0;
-    const float *gPtr = fs->gaussian;
-    if ((y > fs->radius) && (y < (fs->height - fs->radius))) {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, y + r);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    } else {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            int validH = rsClamp((int)y + r, (int)0, (int)(fs->height - 1));
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, validH);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    }
-
-    float3 temp = rsMatrixMultiply(&colorMat, blurredPixel);
-    temp = clamp(temp, 0.f, 255.f);
-    out->xyz = convert_uchar3(temp);
-    out->w = 0xff;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..7f7bdcf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5 * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7*sqrt(desired_scale) - 1.3;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(*in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
+    // TODO:  add half_exp once implemented
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    *out = convert_uchar4(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
new file mode 100644
index 0000000..3612509
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "vignette_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
new file mode 100644
index 0000000..b714e9b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "vignette_approx.rsh"
+