Merge "Add support for CMAS warning notifications over CDMA."
diff --git a/api/current.txt b/api/current.txt
index ad84895..6056bf7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26489,6 +26489,7 @@
     ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int);
     method public deprecated boolean getConsiderGoneChildrenWhenMeasuring();
     method public android.graphics.drawable.Drawable getForeground();
+    method public int getForegroundGravity();
     method public boolean getMeasureAllChildren();
     method protected void onLayout(boolean, int, int, int, int);
     method public void setForeground(android.graphics.drawable.Drawable);
@@ -26717,6 +26718,7 @@
     ctor public LinearLayout(android.content.Context, android.util.AttributeSet);
     ctor public LinearLayout(android.content.Context, android.util.AttributeSet, int);
     method public int getBaselineAlignedChildIndex();
+    method public android.graphics.drawable.Drawable getDividerDrawable();
     method public int getDividerPadding();
     method public int getOrientation();
     method public int getShowDividers();
@@ -27141,6 +27143,7 @@
     ctor public RelativeLayout(android.content.Context);
     ctor public RelativeLayout(android.content.Context, android.util.AttributeSet);
     ctor public RelativeLayout(android.content.Context, android.util.AttributeSet, int);
+    method public int getGravity();
     method protected void onLayout(boolean, int, int, int, int);
     method public void setGravity(int);
     method public void setHorizontalGravity(int);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index fbcbb32..aa92efb 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -437,6 +437,13 @@
      * instances of the same camera, or across multiple runs of the same
      * program.
      *
+     * <p>If you are using the preview data to create video or still images,
+     * strongly consider using {@link android.media.MediaActionSound} to
+     * properly indicate image capture or recording start/stop to the user.</p>
+     *
+     * @see android.media.MediaActionSound
+     * @see android.graphics.SurfaceTexture
+     * @see android.view.TextureView
      * @param surfaceTexture the {@link SurfaceTexture} to which the preview
      *     images are to be sent or null to remove the current preview surface
      *     texture
@@ -512,13 +519,19 @@
     public native final boolean previewEnabled();
 
     /**
-     * Installs a callback to be invoked for every preview frame in addition
+     * <p>Installs a callback to be invoked for every preview frame in addition
      * to displaying them on the screen.  The callback will be repeatedly called
      * for as long as preview is active.  This method can be called at any time,
-     * even while preview is live.  Any other preview callbacks are overridden.
+     * even while preview is live.  Any other preview callbacks are
+     * overridden.</p>
+     *
+     * <p>If you are using the preview data to create video or still images,
+     * strongly consider using {@link android.media.MediaActionSound} to
+     * properly indicate image capture or recording start/stop to the user.</p>
      *
      * @param cb a callback object that receives a copy of each preview frame,
      *     or null to stop receiving callbacks.
+     * @see android.media.MediaActionSound
      */
     public final void setPreviewCallback(PreviewCallback cb) {
         mPreviewCallback = cb;
@@ -530,13 +543,18 @@
     }
 
     /**
-     * Installs a callback to be invoked for the next preview frame in addition
-     * to displaying it on the screen.  After one invocation, the callback is
-     * cleared. This method can be called any time, even when preview is live.
-     * Any other preview callbacks are overridden.
+     * <p>Installs a callback to be invoked for the next preview frame in
+     * addition to displaying it on the screen.  After one invocation, the
+     * callback is cleared. This method can be called any time, even when
+     * preview is live.  Any other preview callbacks are overridden.</p>
+     *
+     * <p>If you are using the preview data to create video or still images,
+     * strongly consider using {@link android.media.MediaActionSound} to
+     * properly indicate image capture or recording start/stop to the user.</p>
      *
      * @param cb a callback object that receives a copy of the next preview frame,
      *     or null to stop receiving callbacks.
+     * @see android.media.MediaActionSound
      */
     public final void setOneShotPreviewCallback(PreviewCallback cb) {
         mPreviewCallback = cb;
@@ -548,24 +566,30 @@
     private native final void setHasPreviewCallback(boolean installed, boolean manualBuffer);
 
     /**
-     * Installs a callback to be invoked for every preview frame, using buffers
-     * supplied with {@link #addCallbackBuffer(byte[])}, in addition to
+     * <p>Installs a callback to be invoked for every preview frame, using
+     * buffers supplied with {@link #addCallbackBuffer(byte[])}, in addition to
      * displaying them on the screen.  The callback will be repeatedly called
-     * for as long as preview is active and buffers are available.
-     * Any other preview callbacks are overridden.
+     * for as long as preview is active and buffers are available.  Any other
+     * preview callbacks are overridden.</p>
      *
      * <p>The purpose of this method is to improve preview efficiency and frame
      * rate by allowing preview frame memory reuse.  You must call
      * {@link #addCallbackBuffer(byte[])} at some point -- before or after
-     * calling this method -- or no callbacks will received.
+     * calling this method -- or no callbacks will received.</p>
      *
-     * The buffer queue will be cleared if this method is called with a null
+     * <p>The buffer queue will be cleared if this method is called with a null
      * callback, {@link #setPreviewCallback(Camera.PreviewCallback)} is called,
-     * or {@link #setOneShotPreviewCallback(Camera.PreviewCallback)} is called.
+     * or {@link #setOneShotPreviewCallback(Camera.PreviewCallback)} is
+     * called.</p>
+     *
+     * <p>If you are using the preview data to create video or still images,
+     * strongly consider using {@link android.media.MediaActionSound} to
+     * properly indicate image capture or recording start/stop to the user.</p>
      *
      * @param cb a callback object that receives a copy of the preview frame,
      *     or null to stop receiving callbacks and clear the buffer queue.
      * @see #addCallbackBuffer(byte[])
+     * @see android.media.MediaActionSound
      */
     public final void setPreviewCallbackWithBuffer(PreviewCallback cb) {
         mPreviewCallback = cb;
@@ -834,10 +858,15 @@
      * the focus position. Applications must call cancelAutoFocus to reset the
      * focus.</p>
      *
+     * <p>If autofocus is successful, consider using
+     * {@link android.media.MediaActionSound} to properly play back an autofocus
+     * success sound to the user.</p>
+     *
      * @param cb the callback to run
      * @see #cancelAutoFocus()
      * @see android.hardware.Camera.Parameters#setAutoExposureLock(boolean)
      * @see android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean)
+     * @see android.media.MediaActionSound
      */
     public final void autoFocus(AutoFocusCallback cb)
     {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 516ce2a..2dcea80 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1,4 +1,4 @@
- /*
+/*
  * Copyright (C) 2006 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -363,40 +363,67 @@
         // direction of the layout or line.  XXX: Should they?
         // They are evaluated at each line.
         if (mSpannedText) {
-            int previousLineBottom = getLineTop(firstLine);
-            int previousLineEnd = getLineStart(firstLine);
-            ParagraphStyle[] spans = NO_PARA_SPANS;
-            TextPaint paint = mPaint;
-            CharSequence buf = mText;
-            int spanEnd = 0;
-            final int width = mWidth;
-            Spanned sp = (Spanned) buf;
-            int textLength = buf.length();
-            for (int i = firstLine; i <= lastLine; i++) {
-                int start = previousLineEnd;
-                int end = getLineStart(i + 1);
-                previousLineEnd = end;
+            if (lineBackgroundSpans == null) {
+                lineBackgroundSpans = new SpanSet<LineBackgroundSpan>(LineBackgroundSpan.class);
+            }
 
-                int ltop = previousLineBottom;
-                int lbottom = getLineTop(i + 1);
-                previousLineBottom = lbottom;
-                int lbaseline = lbottom - getLineDescent(i);
+            Spanned buffer = (Spanned) mText;
+            int textLength = buffer.length();
+            lineBackgroundSpans.init(buffer, 0, textLength);
 
-                if (start >= spanEnd) {
-                    // These should be infrequent, so we'll use this so that
-                    // we don't have to check as often.
-                    spanEnd = sp.nextSpanTransition(start, textLength, LineBackgroundSpan.class);
-                    // All LineBackgroundSpans on a line contribute to its background.
-                    spans = getParagraphSpans(sp, start, end, LineBackgroundSpan.class);
-                }
+            if (lineBackgroundSpans.numberOfSpans > 0) {
+                int previousLineBottom = getLineTop(firstLine);
+                int previousLineEnd = getLineStart(firstLine);
+                ParagraphStyle[] spans = NO_PARA_SPANS;
+                int spansLength = 0;
+                TextPaint paint = mPaint;
+                int spanEnd = 0;
+                final int width = mWidth;
+                for (int i = firstLine; i <= lastLine; i++) {
+                    int start = previousLineEnd;
+                    int end = getLineStart(i + 1);
+                    previousLineEnd = end;
 
-                for (int n = 0; n < spans.length; n++) {
-                    LineBackgroundSpan back = (LineBackgroundSpan) spans[n];
-                    back.drawBackground(canvas, paint, 0, width,
-                            ltop, lbaseline, lbottom,
-                            buf, start, end, i);
+                    int ltop = previousLineBottom;
+                    int lbottom = getLineTop(i + 1);
+                    previousLineBottom = lbottom;
+                    int lbaseline = lbottom - getLineDescent(i);
+
+                    if (start >= spanEnd) {
+                        // These should be infrequent, so we'll use this so that
+                        // we don't have to check as often.
+                        spanEnd = lineBackgroundSpans.getNextTransition(start, textLength);
+                        // All LineBackgroundSpans on a line contribute to its background.
+                        spansLength = 0;
+                        // Duplication of the logic of getParagraphSpans
+                        if (start != end || start == 0) {
+                            // Equivalent to a getSpans(start, end), but filling the 'spans' local
+                            // array instead to reduce memory allocation
+                            for (int j = 0; j < lineBackgroundSpans.numberOfSpans; j++) {
+                                // equal test is valid since both intervals are not empty by construction
+                                if (lineBackgroundSpans.spanStarts[j] >= end ||
+                                        lineBackgroundSpans.spanEnds[j] <= start) continue;
+                                if (spansLength == spans.length) {
+                                    // The spans array needs to be expanded
+                                    int newSize = ArrayUtils.idealObjectArraySize(2 * spansLength);
+                                    ParagraphStyle[] newSpans = new ParagraphStyle[newSize];
+                                    System.arraycopy(spans, 0, newSpans, 0, spansLength);
+                                    spans = newSpans;
+                                }
+                                spans[spansLength++] = lineBackgroundSpans.spans[j];
+                            }
+                        }
+                    }
+
+                    for (int n = 0; n < spansLength; n++) {
+                        LineBackgroundSpan lineBackgroundSpan = (LineBackgroundSpan) spans[n];
+                        lineBackgroundSpan.drawBackground(canvas, paint, 0, width,
+                                ltop, lbaseline, lbottom,
+                                buffer, start, end, i);
+                    }
                 }
             }
+            lineBackgroundSpans.recycle();
         }
 
         // There can be a highlight even without spans if we are drawing
@@ -1830,6 +1857,7 @@
     private static final Rect sTempRect = new Rect();
     private boolean mSpannedText;
     private TextDirectionHeuristic mTextDir;
+    private SpanSet<LineBackgroundSpan> lineBackgroundSpans;
 
     public static final int DIR_LEFT_TO_RIGHT = 1;
     public static final int DIR_RIGHT_TO_LEFT = -1;
diff --git a/core/java/android/text/SpanSet.java b/core/java/android/text/SpanSet.java
new file mode 100644
index 0000000..3ca6033
--- /dev/null
+++ b/core/java/android/text/SpanSet.java
@@ -0,0 +1,111 @@
+/*
+ * 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.text;
+
+import java.lang.reflect.Array;
+
+/**
+ * A cached set of spans. Caches the result of {@link Spanned#getSpans(int, int, Class)} and then
+ * provides faster access to {@link Spanned#nextSpanTransition(int, int, Class)}.
+ *
+ * Fields are left public for a convenient direct access.
+ *
+ * Note that empty spans are ignored by this class.
+ * @hide
+ */
+public class SpanSet<E> {
+    private final Class<? extends E> classType;
+
+    int numberOfSpans;
+    E[] spans;
+    int[] spanStarts;
+    int[] spanEnds;
+    int[] spanFlags;
+
+    SpanSet(Class<? extends E> type) {
+        classType = type;
+        numberOfSpans = 0;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void init(Spanned spanned, int start, int limit) {
+        final E[] allSpans = spanned.getSpans(start, limit, classType);
+        final int length = allSpans.length;
+
+        if (length > 0 && (spans == null || spans.length < length)) {
+            // These arrays may end up being too large because of the discarded empty spans
+            spans = (E[]) Array.newInstance(classType, length);
+            spanStarts = new int[length];
+            spanEnds = new int[length];
+            spanFlags = new int[length];
+        }
+
+        numberOfSpans = 0;
+        for (int i = 0; i < length; i++) {
+            final E span = allSpans[i];
+
+            final int spanStart = spanned.getSpanStart(span);
+            final int spanEnd = spanned.getSpanEnd(span);
+            if (spanStart == spanEnd) continue;
+
+            final int spanFlag = spanned.getSpanFlags(span);
+
+            spans[numberOfSpans] = span;
+            spanStarts[numberOfSpans] = spanStart;
+            spanEnds[numberOfSpans] = spanEnd;
+            spanFlags[numberOfSpans] = spanFlag;
+
+            numberOfSpans++;
+        }
+    }
+
+    /**
+     * Returns true if there are spans intersecting the given interval.
+     * @param end must be strictly greater than start
+     */
+    public boolean hasSpansIntersecting(int start, int end) {
+        for (int i = 0; i < numberOfSpans; i++) {
+            // equal test is valid since both intervals are not empty by construction
+            if (spanStarts[i] >= end || spanEnds[i] <= start) continue;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Similar to {@link Spanned#nextSpanTransition(int, int, Class)}
+     */
+    int getNextTransition(int start, int limit) {
+        for (int i = 0; i < numberOfSpans; i++) {
+            final int spanStart = spanStarts[i];
+            final int spanEnd = spanEnds[i];
+            if (spanStart > start && spanStart < limit) limit = spanStart;
+            if (spanEnd > start && spanEnd < limit) limit = spanEnd;
+        }
+        return limit;
+    }
+
+    /**
+     * Removes all internal references to the spans to avoid memory leaks.
+     */
+    public void recycle() {
+        // The spans array is guaranteed to be not null when numberOfSpans is > 0
+        for (int i = 0; i < numberOfSpans; i++) {
+            spans[i] = null; // prevent a leak: no reference kept when TextLine is recycled
+        }
+    }
+}
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1e8a2f7..0d2835a 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -30,8 +30,6 @@
 
 import com.android.internal.util.ArrayUtils;
 
-import java.lang.reflect.Array;
-
 /**
  * Represents a line of styled text, for measuring in visual order and
  * for rendering.
@@ -860,78 +858,6 @@
         return runIsRtl ? -ret : ret;
     }
 
-    private static class SpanSet<E> {
-        int numberOfSpans;
-        E[] spans;
-        int[] spanStarts;
-        int[] spanEnds;
-        int[] spanFlags;
-        final Class<? extends E> classType;
-
-        SpanSet(Class<? extends E> type) {
-            classType = type;
-            numberOfSpans = 0;
-        }
-
-        @SuppressWarnings("unchecked")
-        public void init(Spanned spanned, int start, int limit) {
-            final E[] allSpans = spanned.getSpans(start, limit, classType);
-            final int length = allSpans.length;
-
-            if (length > 0 && (spans == null || spans.length < length)) {
-                // These arrays may end up being too large because of empty spans
-                spans = (E[]) Array.newInstance(classType, length);
-                spanStarts = new int[length];
-                spanEnds = new int[length];
-                spanFlags = new int[length];
-            }
-
-            numberOfSpans = 0;
-            for (int i = 0; i < length; i++) {
-                final E span = allSpans[i];
-
-                final int spanStart = spanned.getSpanStart(span);
-                final int spanEnd = spanned.getSpanEnd(span);
-                if (spanStart == spanEnd) continue;
-
-                final int spanFlag = spanned.getSpanFlags(span);
-
-                spans[numberOfSpans] = span;
-                spanStarts[numberOfSpans] = spanStart;
-                spanEnds[numberOfSpans] = spanEnd;
-                spanFlags[numberOfSpans] = spanFlag;
-
-                numberOfSpans++;
-            }
-        }
-
-        public boolean hasSpansIntersecting(int start, int end) {
-            for (int i = 0; i < numberOfSpans; i++) {
-                // equal test is valid since both intervals are not empty by construction
-                if (spanStarts[i] >= end || spanEnds[i] <= start) continue;
-                return true;
-            }
-            return false;
-        }
-
-        int getNextTransition(int start, int limit) {
-            for (int i = 0; i < numberOfSpans; i++) {
-                final int spanStart = spanStarts[i];
-                final int spanEnd = spanEnds[i];
-                if (spanStart > start && spanStart < limit) limit = spanStart;
-                if (spanEnd > start && spanEnd < limit) limit = spanEnd;
-            }
-            return limit;
-        }
-
-        public void recycle() {
-            // The spans array is guaranteed to be not null when numberOfSpans is > 0
-            for (int i = 0; i < numberOfSpans; i++) {
-                spans[i] = null; // prevent a leak: no reference kept when TextLine is recycled
-            }
-        }
-    }
-
     /**
      * Utility function for handling a unidirectional run.  The run must not
      * contain tabs or emoji but can contain styles.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bf48ff2..1edcff6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10456,10 +10456,10 @@
             if (mHardwareLayer == null) {
                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
                         width, height, isOpaque());
-                mLocalDirtyRect.setEmpty();
+                mLocalDirtyRect.set(0, 0, width, height);
             } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
                 mHardwareLayer.resize(width, height);
-                mLocalDirtyRect.setEmpty();
+                mLocalDirtyRect.set(0, 0, width, height);
             }
 
             // The layer is not valid if the underlying GPU resources cannot be allocated
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index da98884..d019d8c 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -122,10 +122,25 @@
     }
 
     /**
+     * Describes how the foreground is positioned.
+     *
+     * @return foreground gravity.
+     *
+     * @see #setForegroundGravity(int)
+     *
+     * @attr ref android.R.styleable#FrameLayout_foregroundGravity
+     */
+    public int getForegroundGravity() {
+        return mForegroundGravity;
+    }
+
+    /**
      * Describes how the foreground is positioned. Defaults to START and TOP.
      *
      * @param foregroundGravity See {@link android.view.Gravity}
      *
+     * @see #getForegroundGravity()
+     *
      * @attr ref android.R.styleable#FrameLayout_foregroundGravity
      */
     @android.view.RemotableViewMethod
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index a1bea43..5ed005f 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -235,9 +235,24 @@
     }
 
     /**
+     * @return the divider Drawable that will divide each item.
+     *
+     * @see #setDividerDrawable(Drawable)
+     *
+     * @attr ref android.R.styleable#LinearLayout_divider
+     */
+    public Drawable getDividerDrawable() {
+        return mDivider;
+    }
+
+    /**
      * Set a drawable to be used as a divider between items.
+     *
      * @param divider Drawable that will divide each item.
+     *
      * @see #setShowDividers(int)
+     *
+     * @attr ref android.R.styleable#LinearLayout_divider
      */
     public void setDividerDrawable(Drawable divider) {
         if (divider == mDivider) {
@@ -398,6 +413,8 @@
      * 
      * @return True to measure children with a weight using the minimum
      *         size of the largest child, false otherwise.
+     *
+     * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild
      */
     public boolean isMeasureWithLargestChildEnabled() {
         return mUseLargestChild;
@@ -412,6 +429,8 @@
      * 
      * @param enabled True to measure children with a weight using the
      *        minimum size of the largest child, false otherwise.
+     *
+     * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild
      */
     @android.view.RemotableViewMethod
     public void setMeasureWithLargestChildEnabled(boolean enabled) {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index e4b8f34..29cf000 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -219,6 +219,20 @@
     }
 
     /**
+     * Describes how the child views are positioned.
+     *
+     * @return the gravity.
+     *
+     * @see #setGravity(int)
+     * @see android.view.Gravity
+     *
+     * @attr ref android.R.styleable#RelativeLayout_gravity
+     */
+    public int getGravity() {
+        return mGravity;
+    }
+
+    /**
      * Describes how the child views are positioned. Defaults to
      * <code>Gravity.LEFT | Gravity.TOP</code>.
      *
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index b870cee..6331b6d 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -232,6 +232,8 @@
      * <p>Indicates whether all columns are shrinkable or not.</p>
      *
      * @return true if all columns are shrinkable, false otherwise
+     *
+     * @attr ref android.R.styleable#TableLayout_shrinkColumns
      */
     public boolean isShrinkAllColumns() {
         return mShrinkAllColumns;
@@ -252,6 +254,8 @@
      * <p>Indicates whether all columns are stretchable or not.</p>
      *
      * @return true if all columns are stretchable, false otherwise
+     *
+     * @attr ref android.R.styleable#TableLayout_stretchColumns
      */
     public boolean isStretchAllColumns() {
         return mStretchAllColumns;
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index 5ee41e6..4b1b40e 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -159,11 +159,13 @@
     return DRM_NO_ERROR;
 }
 
+// make sure that lower-case letters are used.
 const String8 FwdLockEngine::FileSuffixes[] = {
     String8(".fl"),
     String8(".dm"),
 };
 
+// make sure that lower-case letters are used.
 const String8 FwdLockEngine::MimeTypes[] = {
     String8("application/x-android-drm-fl"),
     String8("application/vnd.oma.drm.message"),
@@ -184,8 +186,10 @@
 }
 
 bool FwdLockEngine::IsMimeTypeSupported(const String8& mime) {
+    String8 tmp(mime);
+    tmp.toLower();
     for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) {
-        if (mime == MimeTypes[i]) {
+        if (tmp == MimeTypes[i]) {
             return true;
         }
     }
@@ -193,8 +197,10 @@
 }
 
 bool FwdLockEngine::IsFileSuffixSupported(const String8& suffix) {
+    String8 tmp(suffix);
+    tmp.toLower();
     for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) {
-        if (suffix == FileSuffixes[i]) {
+        if (tmp == FileSuffixes[i]) {
             return true;
         }
     }
@@ -220,7 +226,6 @@
     bool result = false;
 
     String8 extString = path.getPathExtension();
-    extString.toLower();
     return IsFileSuffixSupported(extString);
 }
 
@@ -331,8 +336,6 @@
 
     LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");
 
-    mimeStr.toLower();
-
     /* Checks whether
     * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
     * 2. if one of them is empty string and if other is known then its a DRM Content Object.
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
index 0ffc0a7..a3eac3e 100644
--- a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "DrmPassthruPlugIn"
 #include <utils/Log.h>
 
@@ -58,7 +58,7 @@
 
 DrmConstraints* DrmPassthruPlugIn::onGetConstraints(
         int uniqueId, const String8* path, int action) {
-    ALOGD("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId);
     DrmConstraints* drmConstraints = new DrmConstraints();
 
     String8 value("dummy_available_time");
@@ -73,7 +73,7 @@
 }
 
 DrmInfoStatus* DrmPassthruPlugIn::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
-    ALOGD("DrmPassthruPlugIn::onProcessDrmInfo - Enter : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Enter : %d", uniqueId);
     DrmInfoStatus* drmInfoStatus = NULL;
     if (NULL != drmInfo) {
         switch (drmInfo->getInfoType()) {
@@ -102,28 +102,28 @@
         }
         }
     }
-    ALOGD("DrmPassthruPlugIn::onProcessDrmInfo - Exit");
+    ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Exit");
     return drmInfoStatus;
 }
 
 status_t DrmPassthruPlugIn::onSetOnInfoListener(
             int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
-    ALOGD("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 status_t DrmPassthruPlugIn::onInitialize(int uniqueId) {
-    ALOGD("DrmPassthruPlugIn::onInitialize : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onInitialize : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 status_t DrmPassthruPlugIn::onTerminate(int uniqueId) {
-    ALOGD("DrmPassthruPlugIn::onTerminate : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onTerminate : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 DrmSupportInfo* DrmPassthruPlugIn::onGetSupportInfo(int uniqueId) {
-    ALOGD("DrmPassthruPlugIn::onGetSupportInfo : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onGetSupportInfo : %d", uniqueId);
     DrmSupportInfo* drmSupportInfo = new DrmSupportInfo();
     // Add mimetype's
     drmSupportInfo->addMimeType(String8("application/vnd.passthru.drm"));
@@ -136,12 +136,12 @@
 
 status_t DrmPassthruPlugIn::onSaveRights(int uniqueId, const DrmRights& drmRights,
             const String8& rightsPath, const String8& contentPath) {
-    ALOGD("DrmPassthruPlugIn::onSaveRights : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onSaveRights : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 DrmInfo* DrmPassthruPlugIn::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
-    ALOGD("DrmPassthruPlugIn::onAcquireDrmInfo : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onAcquireDrmInfo : %d", uniqueId);
     DrmInfo* drmInfo = NULL;
 
     if (NULL != drmInfoRequest) {
@@ -157,65 +157,65 @@
 }
 
 bool DrmPassthruPlugIn::onCanHandle(int uniqueId, const String8& path) {
-    ALOGD("DrmPassthruPlugIn::canHandle: %s ", path.string());
+    ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.string());
     String8 extension = path.getPathExtension();
     extension.toLower();
     return (String8(".passthru") == extension);
 }
 
 String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, const String8& path) {
-    ALOGD("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId);
     return String8("video/passthru");
 }
 
 int DrmPassthruPlugIn::onGetDrmObjectType(
             int uniqueId, const String8& path, const String8& mimeType) {
-    ALOGD("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId);
     return DrmObjectType::UNKNOWN;
 }
 
 int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& path, int action) {
-    ALOGD("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId);
     int rightsStatus = RightsStatus::RIGHTS_VALID;
     return rightsStatus;
 }
 
 status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
             int action, bool reserve) {
-    ALOGD("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
             int playbackStatus, int64_t position) {
-    ALOGD("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 bool DrmPassthruPlugIn::onValidateAction(int uniqueId, const String8& path,
             int action, const ActionDescription& description) {
-    ALOGD("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId);
     return true;
 }
 
 status_t DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& path) {
-    ALOGD("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 status_t DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) {
-    ALOGD("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 status_t DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int convertId) {
-    ALOGD("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 DrmConvertedStatus* DrmPassthruPlugIn::onConvertData(
             int uniqueId, int convertId, const DrmBuffer* inputData) {
-    ALOGD("DrmPassthruPlugIn::onConvertData() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onConvertData() : %d", uniqueId);
     DrmBuffer* convertedData = NULL;
 
     if (NULL != inputData && 0 < inputData->length) {
@@ -229,13 +229,13 @@
 }
 
 DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int convertId) {
-    ALOGD("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId);
     return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/);
 }
 
 status_t DrmPassthruPlugIn::onOpenDecryptSession(
             int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) {
-    ALOGD("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId);
 
 #ifdef ENABLE_PASSTHRU_DECRYPTION
     decryptHandle->mimeType = String8("video/passthru");
@@ -254,7 +254,7 @@
 }
 
 status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
-    ALOGD("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId);
     if (NULL != decryptHandle) {
         if (NULL != decryptHandle->decryptInfo) {
             delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
@@ -266,34 +266,40 @@
 
 status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
             int decryptUnitId, const DrmBuffer* headerInfo) {
-    ALOGD("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
             int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
-    ALOGD("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId);
     /**
      * As a workaround implementation passthru would copy the given
      * encrypted buffer as it is to decrypted buffer. Note, decBuffer
      * memory has to be allocated by the caller.
      */
     if (NULL != (*decBuffer) && 0 < (*decBuffer)->length) {
-        memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length);
-        (*decBuffer)->length = encBuffer->length;
+        if ((*decBuffer)->length >= encBuffer->length) {
+            memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length);
+            (*decBuffer)->length = encBuffer->length;
+        } else {
+            ALOGE("decBuffer size (%d) too small to hold %d bytes",
+                (*decBuffer)->length, encBuffer->length);
+            return DRM_ERROR_UNKNOWN;
+        }
     }
     return DRM_NO_ERROR;
 }
 
 status_t DrmPassthruPlugIn::onFinalizeDecryptUnit(
             int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
-    ALOGD("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId);
     return DRM_NO_ERROR;
 }
 
 ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* decryptHandle,
             void* buffer, ssize_t numBytes, off64_t offset) {
-    ALOGD("DrmPassthruPlugIn::onPread() : %d", uniqueId);
+    ALOGV("DrmPassthruPlugIn::onPread() : %d", uniqueId);
     return 0;
 }
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 24f52e0..a884d8e 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -826,7 +826,7 @@
     while (!mReader.eof()) {
         int op = mReader.readInt();
         if (op & OP_MAY_BE_SKIPPED_MASK) {
-            int32_t skip = mReader.readInt() * 4;
+            int32_t skip = mReader.readInt();
             if (CC_LIKELY(flags & kReplayFlag_ClipChildren)) {
                 mReader.skip(skip);
                 DISPLAY_LIST_LOGD("%s%s skipping %d bytes", (char*) indent,
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index abe8b82..43617e7 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -656,9 +656,8 @@
         if (reject) {
             mWriter.writeInt(OP_MAY_BE_SKIPPED_MASK | drawOp);
             mWriter.writeInt(0xdeaddead);
-            uint32_t* location = reject ?
-                    mWriter.peek32(mWriter.size() - sizeof(int32_t)) : NULL;
-            return location;
+            mBufferSize = mWriter.size();
+            return mWriter.peek32(mBufferSize - sizeof(int32_t));
         }
         mWriter.writeInt(drawOp);
         return NULL;
@@ -666,8 +665,7 @@
 
     inline void addSkip(uint32_t* location) {
         if (location) {
-            *location = (int32_t) (mWriter.peek32(
-                    mWriter.size() - sizeof(int32_t)) - location);
+            *location = (int32_t) (mWriter.size() - mBufferSize);
         }
     }
 
@@ -822,6 +820,7 @@
     Vector<SkMatrix*> mMatrices;
 
     SkWriter32 mWriter;
+    uint32_t mBufferSize;
 
     int mRestoreSaveCount;
 
diff --git a/libs/rs/tests/Android.mk b/libs/rs/tests/Android.mk
index 197e862..627ff72 100644
--- a/libs/rs/tests/Android.mk
+++ b/libs/rs/tests/Android.mk
@@ -22,9 +22,15 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_C_INCLUDES +=  .. \
-	frameworks/base/libs/rs \
-	out/target/product/stingray/obj/SHARED_LIBRARIES/libRS_intermediates	
+intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
+librs_generated_headers := \
+    $(intermediates)/rsgApiStructs.h \
+    $(intermediates)/rsgApiFuncDecl.h
+LOCAL_GENERATED_SOURCES := $(librs_generated_headers)
+
+LOCAL_C_INCLUDES += frameworks/base/libs/rs
+LOCAL_C_INCLUDES += $(intermediates)
+
 
 include $(BUILD_EXECUTABLE)