Merge "API changes to Telephony per API review" into lmp-preview-dev
diff --git a/api/current.txt b/api/current.txt
index cf444d2..012ecb8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -33748,11 +33748,17 @@
 
   public static final class CaptioningManager.CaptionStyle {
     method public android.graphics.Typeface getTypeface();
+    method public boolean hasBackgroundColor();
+    method public boolean hasEdgeColor();
+    method public boolean hasEdgeType();
+    method public boolean hasForegroundColor();
+    method public boolean hasWindowColor();
     field public static final int EDGE_TYPE_DEPRESSED = 4; // 0x4
     field public static final int EDGE_TYPE_DROP_SHADOW = 2; // 0x2
     field public static final int EDGE_TYPE_NONE = 0; // 0x0
     field public static final int EDGE_TYPE_OUTLINE = 1; // 0x1
     field public static final int EDGE_TYPE_RAISED = 3; // 0x3
+    field public static final int EDGE_TYPE_UNSPECIFIED = -1; // 0xffffffff
     field public final int backgroundColor;
     field public final int edgeColor;
     field public final int edgeType;
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index a0134d6..334ff43 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -16,6 +16,8 @@
 
 package android.view.accessibility;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -78,6 +80,7 @@
      *         language
      * @hide
      */
+    @Nullable
     public final String getRawLocale() {
         return Secure.getString(mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
     }
@@ -86,6 +89,7 @@
      * @return the locale for the user's preferred captioning language, or null
      *         if not specified
      */
+    @Nullable
     public final Locale getLocale() {
         final String rawLocale = getRawLocale();
         if (!TextUtils.isEmpty(rawLocale)) {
@@ -125,6 +129,7 @@
      * @return the user's preferred visual properties for captions as a
      *         {@link CaptionStyle}, or the default style if not specified
      */
+    @NonNull
     public CaptionStyle getUserStyle() {
         final int preset = getRawUserStyle();
         if (preset == CaptionStyle.PRESET_CUSTOM) {
@@ -140,17 +145,19 @@
      *
      * @param listener the listener to add
      */
-    public void addCaptioningChangeListener(CaptioningChangeListener listener) {
+    public void addCaptioningChangeListener(@NonNull CaptioningChangeListener listener) {
         synchronized (mListeners) {
             if (mListeners.isEmpty()) {
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_ENABLED);
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR);
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR);
+                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR);
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE);
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR);
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE);
                 registerObserver(Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
+                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_PRESET);
             }
 
             mListeners.add(listener);
@@ -167,7 +174,7 @@
      *
      * @param listener the listener to remove
      */
-    public void removeCaptioningChangeListener(CaptioningChangeListener listener) {
+    public void removeCaptioningChangeListener(@NonNull CaptioningChangeListener listener) {
         synchronized (mListeners) {
             mListeners.remove(listener);
 
@@ -253,11 +260,18 @@
         /** Packed value for a color of 'none' and a cached opacity of 100%. */
         private static final int COLOR_NONE_OPAQUE = 0x000000FF;
 
+        /** Packed value for an unspecified color and opacity. */
+        private static final int COLOR_UNSPECIFIED = 0x000001FF;
+
         private static final CaptionStyle WHITE_ON_BLACK;
         private static final CaptionStyle BLACK_ON_WHITE;
         private static final CaptionStyle YELLOW_ON_BLACK;
         private static final CaptionStyle YELLOW_ON_BLUE;
         private static final CaptionStyle DEFAULT_CUSTOM;
+        private static final CaptionStyle UNSPECIFIED;
+
+        /** The default caption style used to fill in unspecified values. @hide */
+        public static final CaptionStyle DEFAULT;
 
         /** @hide */
         public static final CaptionStyle[] PRESETS;
@@ -265,6 +279,9 @@
         /** @hide */
         public static final int PRESET_CUSTOM = -1;
 
+        /** Unspecified edge type value. */
+        public static final int EDGE_TYPE_UNSPECIFIED = -1;
+
         /** Edge type value specifying no character edges. */
         public static final int EDGE_TYPE_NONE = 0;
 
@@ -289,6 +306,7 @@
         /**
          * The preferred edge type for video captions, one of:
          * <ul>
+         * <li>{@link #EDGE_TYPE_UNSPECIFIED}
          * <li>{@link #EDGE_TYPE_NONE}
          * <li>{@link #EDGE_TYPE_OUTLINE}
          * <li>{@link #EDGE_TYPE_DROP_SHADOW}
@@ -326,9 +344,81 @@
         }
 
         /**
+         * Applies a caption style, overriding any properties that are specified
+         * in the overlay caption.
+         *
+         * @param overlay The style to apply
+         * @return A caption style with the overlay style applied
+         * @hide
+         */
+        @NonNull
+        public CaptionStyle applyStyle(@NonNull CaptionStyle overlay) {
+            final int newForegroundColor = overlay.hasForegroundColor() ?
+                    overlay.foregroundColor : foregroundColor;
+            final int newBackgroundColor = overlay.hasBackgroundColor() ?
+                    overlay.backgroundColor : backgroundColor;
+            final int newEdgeType = overlay.hasEdgeType() ?
+                    overlay.edgeType : edgeType;
+            final int newEdgeColor = overlay.hasEdgeColor() ?
+                    overlay.edgeColor : edgeColor;
+            final int newWindowColor = overlay.hasWindowColor() ?
+                    overlay.windowColor : windowColor;
+            final String newRawTypeface = overlay.mRawTypeface != null ?
+                    overlay.mRawTypeface : mRawTypeface;
+            return new CaptionStyle(newForegroundColor, newBackgroundColor, newEdgeType,
+                    newEdgeColor, newWindowColor, newRawTypeface);
+        }
+
+        /**
+         * @return {@code true} if the user has specified a background color
+         *         that should override the application default, {@code false}
+         *         otherwise
+         */
+        public boolean hasBackgroundColor() {
+            return backgroundColor != COLOR_UNSPECIFIED;
+        }
+
+        /**
+         * @return {@code true} if the user has specified a foreground color
+         *         that should override the application default, {@code false}
+         *         otherwise
+         */
+        public boolean hasForegroundColor() {
+            return foregroundColor != COLOR_UNSPECIFIED;
+        }
+
+        /**
+         * @return {@code true} if the user has specified an edge type that
+         *         should override the application default, {@code false}
+         *         otherwise
+         */
+        public boolean hasEdgeType() {
+            return edgeType != EDGE_TYPE_UNSPECIFIED;
+        }
+
+        /**
+         * @return {@code true} if the user has specified an edge color that
+         *         should override the application default, {@code false}
+         *         otherwise
+         */
+        public boolean hasEdgeColor() {
+            return edgeColor != COLOR_UNSPECIFIED;
+        }
+
+        /**
+         * @return {@code true} if the user has specified a window color that
+         *         should override the application default, {@code false}
+         *         otherwise
+         */
+        public boolean hasWindowColor() {
+            return windowColor != COLOR_UNSPECIFIED;
+        }
+
+        /**
          * @return the preferred {@link Typeface} for video captions, or null if
          *         not specified
          */
+        @Nullable
         public Typeface getTypeface() {
             if (mParsedTypeface == null && !TextUtils.isEmpty(mRawTypeface)) {
                 mParsedTypeface = Typeface.create(mRawTypeface, Typeface.NORMAL);
@@ -339,6 +429,7 @@
         /**
          * @hide
          */
+        @NonNull
         public static CaptionStyle getCustomStyle(ContentResolver cr) {
             final CaptionStyle defStyle = CaptionStyle.DEFAULT_CUSTOM;
             final int foregroundColor = Secure.getInt(
@@ -370,12 +461,17 @@
                     Color.BLACK, COLOR_NONE_OPAQUE, null);
             YELLOW_ON_BLUE = new CaptionStyle(Color.YELLOW, Color.BLUE, EDGE_TYPE_NONE,
                     Color.BLACK, COLOR_NONE_OPAQUE, null);
+            UNSPECIFIED = new CaptionStyle(COLOR_UNSPECIFIED, COLOR_UNSPECIFIED,
+                    EDGE_TYPE_UNSPECIFIED, COLOR_UNSPECIFIED, COLOR_UNSPECIFIED, null);
 
+            // The ordering of these cannot change since we store the index
+            // directly in preferences.
             PRESETS = new CaptionStyle[] {
-                    WHITE_ON_BLACK, BLACK_ON_WHITE, YELLOW_ON_BLACK, YELLOW_ON_BLUE
+                    WHITE_ON_BLACK, BLACK_ON_WHITE, YELLOW_ON_BLACK, YELLOW_ON_BLUE, UNSPECIFIED
             };
 
             DEFAULT_CUSTOM = WHITE_ON_BLACK;
+            DEFAULT = WHITE_ON_BLACK;
         }
     }
 
@@ -389,8 +485,7 @@
          *
          * @param enabled the user's new preferred captioning enabled state
          */
-        public void onEnabledChanged(boolean enabled) {
-        }
+        public void onEnabledChanged(boolean enabled) {}
 
         /**
          * Called when the captioning user style changes.
@@ -398,17 +493,15 @@
          * @param userStyle the user's new preferred style
          * @see CaptioningManager#getUserStyle()
          */
-        public void onUserStyleChanged(CaptionStyle userStyle) {
-        }
+        public void onUserStyleChanged(@NonNull CaptionStyle userStyle) {}
 
         /**
          * Called when the captioning locale changes.
          *
-         * @param locale the preferred captioning locale
+         * @param locale the preferred captioning locale, or {@code null} if not specified
          * @see CaptioningManager#getLocale()
          */
-        public void onLocaleChanged(Locale locale) {
-        }
+        public void onLocaleChanged(@Nullable Locale locale) {}
 
         /**
          * Called when the captioning font scaling factor changes.
@@ -416,7 +509,6 @@
          * @param fontScale the preferred font scaling factor
          * @see CaptioningManager#getFontScale()
          */
-        public void onFontScaleChanged(float fontScale) {
-        }
+        public void onFontScaleChanged(float fontScale) {}
     }
 }
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
index 117463a..2f987e9 100644
--- a/core/java/com/android/internal/widget/SubtitleView.java
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -271,10 +271,13 @@
             style = CaptionStyle.PRESETS[styleId];
         }
 
-        mForegroundColor = style.foregroundColor;
-        mBackgroundColor = style.backgroundColor;
-        mEdgeType = style.edgeType;
-        mEdgeColor = style.edgeColor;
+        final CaptionStyle defStyle = CaptionStyle.DEFAULT;
+        mForegroundColor = style.hasForegroundColor() ?
+                style.foregroundColor : defStyle.foregroundColor;
+        mBackgroundColor = style.hasBackgroundColor() ?
+                style.backgroundColor : defStyle.backgroundColor;
+        mEdgeType = style.hasEdgeType() ? style.edgeType : defStyle.edgeType;
+        mEdgeColor = style.hasEdgeColor() ? style.edgeColor : defStyle.edgeColor;
         mHasMeasurements = false;
 
         final Typeface typeface = style.getTypeface();
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index ec935cc..8e56eec 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -879,8 +879,8 @@
 
 #ifdef USE_MINIKIN
         Layout layout;
-        MinikinUtils::SetLayoutProperties(&layout, paint, flags, typeface);
-        layout.doLayout(textArray + start, count);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+        layout.doLayout(textArray, start, count, contextCount, css);
         drawGlyphsToSkia(canvas, paint, layout, x, y);
 #else
         sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
diff --git a/core/jni/android/graphics/MinikinSkia.cpp b/core/jni/android/graphics/MinikinSkia.cpp
index 243fa10..2b96f1b 100644
--- a/core/jni/android/graphics/MinikinSkia.cpp
+++ b/core/jni/android/graphics/MinikinSkia.cpp
@@ -46,8 +46,10 @@
 static void MinikinFontSkia_SetSkiaPaint(SkTypeface* typeface, SkPaint* skPaint, const MinikinPaint& paint) {
     skPaint->setTypeface(typeface);
     skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-    // TODO: set more paint parameters from Minikin
     skPaint->setTextSize(paint.size);
+    skPaint->setTextScaleX(paint.scaleX);
+    skPaint->setTextSkewX(paint.skewX);
+    MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags);
 }
 
 float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
@@ -96,4 +98,21 @@
     return mTypeface->uniqueID();
 }
 
+uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
+    uint32_t flags = paint->getFlags();
+    SkPaint::Hinting hinting = paint->getHinting();
+    // select only flags that might affect text layout
+    flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
+            SkPaint::kSubpixelText_Flag | SkPaint::kDevKernText_Flag |
+            SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kAutoHinting_Flag |
+            SkPaint::kVerticalText_Flag);
+    flags |= (hinting << 16);
+    return flags;
+}
+
+void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
+    paint->setFlags(paintFlags & SkPaint::kAllFlags);
+    paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
+}
+
 }
diff --git a/core/jni/android/graphics/MinikinSkia.h b/core/jni/android/graphics/MinikinSkia.h
index 1cc2c51..0452c57 100644
--- a/core/jni/android/graphics/MinikinSkia.h
+++ b/core/jni/android/graphics/MinikinSkia.h
@@ -38,6 +38,8 @@
 
     SkTypeface *GetSkTypeface();
 
+    static uint32_t packPaintFlags(const SkPaint* paint);
+    static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
 private:
     SkTypeface *mTypeface;
 };
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index a88b747..a9360ea 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "Minikin"
+#include <cutils/log.h>
+#include <string>
+
 #include "SkPaint.h"
 #include "minikin/Layout.h"
 #include "TypefaceImpl.h"
@@ -23,24 +27,39 @@
 
 namespace android {
 
-void MinikinUtils::SetLayoutProperties(Layout* layout, const SkPaint* paint, int flags,
-    TypefaceImpl* typeface) {
+// Do an sprintf starting at offset n, abort on overflow
+static int snprintfcat(char* buf, int off, int size, const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    int n = vsnprintf(buf + off, size - off, format, args);
+    LOG_ALWAYS_FATAL_IF(n >= size - off, "String overflow in setting layout properties");
+    va_end(args);
+    return off + n;
+}
+
+std::string MinikinUtils::setLayoutProperties(Layout* layout, const SkPaint* paint, int bidiFlags,
+        TypefaceImpl* typeface) {
     TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
     layout->setFontCollection(resolvedFace->fFontCollection);
     FontStyle style = resolvedFace->fStyle;
     char css[256];
-    int off = snprintf(css, sizeof(css),
-        "font-size: %d; font-weight: %d; font-style: %s; -minikin-bidi: %d;",
+    int off = snprintfcat(css, 0, sizeof(css),
+        "font-size: %d; font-scale-x: %f; font-skew-x: %f; -paint-flags: %d;"
+        " font-weight: %d; font-style: %s; -minikin-bidi: %d;",
         (int)paint->getTextSize(),
+        paint->getTextScaleX(),
+        paint->getTextSkewX(),
+        MinikinFontSkia::packPaintFlags(paint),
         style.getWeight() * 100,
         style.getItalic() ? "italic" : "normal",
-        flags);
+        bidiFlags);
     SkString langString = paint->getPaintOptionsAndroid().getLanguage().getTag();
-    off += snprintf(css + off, sizeof(css) - off, " lang: %s;", langString.c_str());
+    off = snprintfcat(css, off, sizeof(css), " lang: %s;", langString.c_str());
     SkPaintOptionsAndroid::FontVariant var = paint->getPaintOptionsAndroid().getFontVariant();
     const char* varstr = var == SkPaintOptionsAndroid::kElegant_Variant ? "elegant" : "compact";
-    off += snprintf(css + off, sizeof(css) - off, " -minikin-variant: %s;", varstr);
+    off = snprintfcat(css, off, sizeof(css), " -minikin-variant: %s;", varstr);
     layout->setProperties(css);
+    return std::string(css);
 }
 
 float MinikinUtils::xOffsetForTextAlign(SkPaint* paint, const Layout& layout) {
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index 997d6e3..ea7eb5d 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -26,10 +26,14 @@
 
 namespace android {
 
+class Layout;
+class TypefaceImpl;
+
 class MinikinUtils {
 public:
-    static void SetLayoutProperties(Layout* layout, const SkPaint* paint, int flags,
-        TypefaceImpl* face);
+    static std::string setLayoutProperties(Layout* layout, const SkPaint* paint, int bidiFlags,
+            TypefaceImpl* typeface);
+
     static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);
 
     // f is a functor of type void f(SkTypeface *, size_t start, size_t end);
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 4000b07..3dc874e 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -520,8 +520,8 @@
 #ifdef USE_MINIKIN
         Layout layout;
         TypefaceImpl* typeface = GraphicsJNI::getNativeTypeface(env, jpaint);
-        MinikinUtils::SetLayoutProperties(&layout, paint, bidiFlags, typeface);
-        layout.doLayout(textArray + index, count);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+        layout.doLayout(textArray, index, count, textLength, css);
         result = layout.getAdvance();
 #else
         TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength,
@@ -554,8 +554,8 @@
 #ifdef USE_MINIKIN
         Layout layout;
         TypefaceImpl* typeface = GraphicsJNI::getNativeTypeface(env, jpaint);
-        MinikinUtils::SetLayoutProperties(&layout, paint, bidiFlags, typeface);
-        layout.doLayout(textArray + start, count);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+        layout.doLayout(textArray, start, count, textLength, css);
         width = layout.getAdvance();
 #else
         TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength,
@@ -582,8 +582,8 @@
 #ifdef USE_MINIKIN
         Layout layout;
         TypefaceImpl* typeface = GraphicsJNI::getNativeTypeface(env, jpaint);
-        MinikinUtils::SetLayoutProperties(&layout, paint, bidiFlags, typeface);
-        layout.doLayout(textArray, textLength);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+        layout.doLayout(textArray, 0, textLength, textLength, css);
         width = layout.getAdvance();
 #else
         TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength,
@@ -617,8 +617,8 @@
 
 #ifdef USE_MINIKIN
         Layout layout;
-        MinikinUtils::SetLayoutProperties(&layout, paint, bidiFlags, typeface);
-        layout.doLayout(text, count);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+        layout.doLayout(text, 0, count, count, css);
         layout.getAdvances(widthsArray);
 #else
         TextLayout::getTextRunAdvances(paint, text, 0, count, count,
@@ -715,8 +715,8 @@
 
 #ifdef USE_MINIKIN
         Layout layout;
-        MinikinUtils::SetLayoutProperties(&layout, paint, flags, typeface);
-        layout.doLayout(text + start, count);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+        layout.doLayout(text, start, count, contextCount, css);
         layout.getAdvances(advancesArray);
         totalAdvance = layout.getAdvance();
 #else
@@ -860,8 +860,8 @@
             jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
 #ifdef USE_MINIKIN
         Layout layout;
-        MinikinUtils::SetLayoutProperties(&layout, paint, bidiFlags, typeface);
-        layout.doLayout(text, count);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+        layout.doLayout(text, 0, count, count, css);
         size_t nGlyphs = layout.nGlyphs();
         uint16_t* glyphs = new uint16_t[nGlyphs];
         SkPoint* pos = new SkPoint[nGlyphs];
@@ -992,8 +992,8 @@
 
 #ifdef USE_MINIKIN
         Layout layout;
-        MinikinUtils::SetLayoutProperties(&layout, &paint, bidiFlags, typeface);
-        layout.doLayout(text, count);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
+        layout.doLayout(text, 0, count, count, css);
         MinikinRect rect;
         layout.getBounds(&rect);
         r.fLeft = rect.mLeft;
diff --git a/core/jni/android/graphics/TypefaceImpl.cpp b/core/jni/android/graphics/TypefaceImpl.cpp
index 786d19c..27df7cf 100644
--- a/core/jni/android/graphics/TypefaceImpl.cpp
+++ b/core/jni/android/graphics/TypefaceImpl.cpp
@@ -32,6 +32,7 @@
 #include <minikin/FontCollection.h>
 #include <minikin/FontFamily.h>
 #include <minikin/Layout.h>
+#include "SkPaint.h"
 #include "MinikinSkia.h"
 #endif
 
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 820da17..a46ccd6 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -702,8 +702,8 @@
         jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
 #ifdef USE_MINIKIN
     Layout layout;
-    MinikinUtils::SetLayoutProperties(&layout, paint, flags, typeface);
-    layout.doLayout(text, count);
+    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+    layout.doLayout(text, 0, count, count, css);
     x += xOffsetForTextAlign(paint, layout.getAdvance());
     renderTextLayout(renderer, &layout, x, y, paint);
 #else
@@ -746,8 +746,8 @@
         int flags, SkPaint* paint, TypefaceImpl* typeface) {
 #ifdef USE_MINIKIN
     Layout layout;
-    MinikinUtils::SetLayoutProperties(&layout, paint, flags, typeface);
-    layout.doLayout(text + start, count);
+    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+    layout.doLayout(text, start, count, contextCount, css);
     x += xOffsetForTextAlign(paint, layout.getAdvance());
     renderTextLayout(renderer, &layout, x, y, paint);
 #else
diff --git a/data/fonts/Roboto-MediumItalic.ttf b/data/fonts/Roboto-MediumItalic.ttf
index a30aa0c..b828205 100644
--- a/data/fonts/Roboto-MediumItalic.ttf
+++ b/data/fonts/Roboto-MediumItalic.ttf
Binary files differ
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 0ee253a..16548d0 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -94,7 +94,7 @@
         boolean changed = super.setVisible(visible, restart);
         if (visible) {
             if (changed || restart) {
-                setFrame(0, true, mCurFrame >= 0);
+                setFrame(0, true, restart || mCurFrame >= 0);
             }
         } else {
             unscheduleSelf(this);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 1512da5..241b89e 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1203,8 +1203,11 @@
 
         st.mAttrStroke = a.extractThemeAttrs();
 
+        // We have an explicit stroke defined, so the default stroke width
+        // must be at least 0 or the current stroke width.
+        final int defaultStrokeWidth = Math.max(0, st.mStrokeWidth);
         final int width = a.getDimensionPixelSize(
-                R.styleable.GradientDrawableStroke_width, st.mStrokeWidth);
+                R.styleable.GradientDrawableStroke_width, defaultStrokeWidth);
         final float dashWidth = a.getDimension(
                 R.styleable.GradientDrawableStroke_dashWidth, st.mStrokeDashWidth);
 
@@ -1406,10 +1409,13 @@
                 outline.setOval(bounds);
                 return true;
             case LINE:
-                float halfStrokeWidth = mStrokePaint.getStrokeWidth() * 0.5f;
-                float centerY = bounds.centerY();
-                int top = (int) Math.floor(centerY - halfStrokeWidth);
-                int bottom = (int) Math.ceil(centerY + halfStrokeWidth);
+                // Hairlines (0-width stroke) must have a non-empty outline for
+                // shadows to draw correctly, so we'll use a very small width.
+                final float halfStrokeWidth = mStrokePaint == null ?
+                        0.0001f : mStrokePaint.getStrokeWidth() * 0.5f;
+                final float centerY = bounds.centerY();
+                final int top = (int) Math.floor(centerY - halfStrokeWidth);
+                final int bottom = (int) Math.ceil(centerY + halfStrokeWidth);
 
                 outline.setRect(bounds.left, top, bounds.right, bottom);
                 return true;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index f0ae00f..dff4f6c 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -153,6 +153,11 @@
 
     // TODO: rename for consistency
     virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
+protected:
+    // NOTE: must override these to avoid calling into super class, which calls GL. These may be
+    // removed once DisplayListRenderer no longer inherits from OpenGLRenderer
+    virtual void onViewportInitialized() {};
+    virtual void onSnapshotRestored() {};
 
 private:
     void insertRestoreToCount();
diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java
index 1c9730f..7977988 100644
--- a/media/java/android/media/WebVttRenderer.java
+++ b/media/java/android/media/WebVttRenderer.java
@@ -1103,6 +1103,9 @@
  */
 class WebVttRenderingWidget extends ViewGroup implements SubtitleTrack.RenderingWidget {
     private static final boolean DEBUG = false;
+
+    private static final CaptionStyle DEFAULT_CAPTION_STYLE = CaptionStyle.DEFAULT;
+
     private static final int DEBUG_REGION_BACKGROUND = 0x800000FF;
     private static final int DEBUG_CUE_BACKGROUND = 0x80FF0000;
 
@@ -1144,7 +1147,8 @@
         this(context, attrs, defStyleAttr, 0);
     }
 
-    public WebVttRenderingWidget(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+    public WebVttRenderingWidget(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
         // Cannot render text over video when layer type is hardware.
@@ -1259,6 +1263,7 @@
     }
 
     private void setCaptionStyle(CaptionStyle captionStyle, float fontSize) {
+        captionStyle = DEFAULT_CAPTION_STYLE.applyStyle(captionStyle);
         mCaptionStyle = captionStyle;
         mFontSize = fontSize;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index 0cc09c8..116d755d 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -61,6 +61,11 @@
 
     @Override
     protected void onBootCompleted() {
+        if (mUseAlternateRecents) {
+            if (mAlternateRecents != null) {
+                mAlternateRecents.onBootCompleted();
+            }
+        }
         mBootCompleted = true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index bb19415..2f6d58f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -153,6 +153,7 @@
     Messenger mService = null;
     Messenger mMessenger;
     RecentsMessageHandler mHandler;
+    boolean mBootCompleted = false;
     boolean mServiceIsBound = false;
     boolean mToggleRecentsUponServiceBound;
     RecentsServiceConnection mConnection = new RecentsServiceConnection();
@@ -182,6 +183,10 @@
         bindToRecentsService(false);
     }
 
+    public void onBootCompleted() {
+        mBootCompleted = true;
+    }
+
     /** Shows the recents */
     public void onShowRecents(boolean triggeredFromAltTab, View statusBarView) {
         if (Console.Enabled) {
@@ -208,7 +213,7 @@
         if (Console.Enabled) {
             Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
         }
-        if (mServiceIsBound) {
+        if (mServiceIsBound && mBootCompleted) {
             // Notify recents to close it
             try {
                 Bundle data = new Bundle();
@@ -278,7 +283,7 @@
 
     /** Updates each of the task animation rects. */
     void updateAnimationRects() {
-        if (mServiceIsBound) {
+        if (mServiceIsBound && mBootCompleted) {
             Resources res = mContext.getResources();
             int statusBarHeight = res.getDimensionPixelSize(
                     com.android.internal.R.dimen.status_bar_height);
diff --git a/services/core/java/com/android/server/task/TaskMapReadFinishedListener.java b/services/core/java/com/android/server/task/TaskMapReadFinishedListener.java
new file mode 100644
index 0000000..c68d8db
--- /dev/null
+++ b/services/core/java/com/android/server/task/TaskMapReadFinishedListener.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 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.server.task;
+
+import java.util.List;
+
+import com.android.server.task.controllers.TaskStatus;
+
+/**
+ * Callback definition for I/O thread to let the TaskManagerService know when
+ * I/O read has completed. Done this way so we don't stall the main thread on
+ * boot.
+ */
+public interface TaskMapReadFinishedListener {
+
+    /**
+     * Called by the {@link TaskStore} at boot, when the disk read is finished.
+     */
+    public void onTaskMapReadFinished(List<TaskStatus> tasks);
+}