Merge "Fix bug 5098288 - Rethink the suite of new themes"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8931675..c566104 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2503,6 +2503,7 @@
                     mAvailThumbnailBitmap = thumbnail;
                     thumbnail = null;
                 }
+                cv.setBitmap(null);
             }
 
         } catch (Exception e) {
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index 7b9bd60..8eb9ba4 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -314,6 +314,7 @@
                     icon.draw(canvas);
                     icon.setBounds(mOldBounds);
                     icon = new BitmapDrawable(getResources(), thumb);
+                    canvas.setBitmap(null);
                 } else if (iconWidth < width && iconHeight < height) {
                     final Bitmap.Config c = Bitmap.Config.ARGB_8888;
                     final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
@@ -326,6 +327,7 @@
                     icon.draw(canvas);
                     icon.setBounds(mOldBounds);
                     icon = new BitmapDrawable(getResources(), thumb);
+                    canvas.setBitmap(null);
                 }
             }
 
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 7336550..5501f38 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -119,22 +119,22 @@
             switch (msg.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        if (DBG) {
+                        if (VDBG) {
                             mMdst.log("MdstHandler connected");
                         }
                         mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj;
                     } else {
-                        if (DBG) {
+                        if (VDBG) {
                             mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1);
                         }
                     }
                     break;
                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                    mMdst.log("Disconnected from DataStateTracker");
+                    if (VDBG) mMdst.log("Disconnected from DataStateTracker");
                     mMdst.mDataConnectionTrackerAc = null;
                     break;
                 default: {
-                    mMdst.log("Ignorning unknown message=" + msg);
+                    if (VDBG) mMdst.log("Ignorning unknown message=" + msg);
                     break;
                 }
             }
@@ -221,13 +221,13 @@
                             mLinkProperties = intent.getParcelableExtra(
                                     Phone.DATA_LINK_PROPERTIES_KEY);
                             if (mLinkProperties == null) {
-                                log("CONNECTED event did not supply link properties.");
+                                loge("CONNECTED event did not supply link properties.");
                                 mLinkProperties = new LinkProperties();
                             }
                             mLinkCapabilities = intent.getParcelableExtra(
                                     Phone.DATA_LINK_CAPABILITIES_KEY);
                             if (mLinkCapabilities == null) {
-                                log("CONNECTED event did not supply link capabilities.");
+                                loge("CONNECTED event did not supply link capabilities.");
                                 mLinkCapabilities = new LinkCapabilities();
                             }
                             setDetailedState(DetailedState.CONNECTED, reason, apnName);
@@ -238,7 +238,7 @@
                     if (TextUtils.equals(reason, Phone.REASON_LINK_PROPERTIES_CHANGED)) {
                         mLinkProperties = intent.getParcelableExtra(Phone.DATA_LINK_PROPERTIES_KEY);
                         if (mLinkProperties == null) {
-                            log("No link property in LINK_PROPERTIES change event.");
+                            loge("No link property in LINK_PROPERTIES change event.");
                             mLinkProperties = new LinkProperties();
                         }
                         // Just update reason field in this NetworkInfo
@@ -269,7 +269,7 @@
                 setDetailedState(DetailedState.FAILED, reason, apnName);
             } else if (intent.getAction().
                     equals(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {
-                if (DBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
+                if (VDBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
                 mMessenger = intent.getParcelableExtra(DataConnectionTracker.EXTRA_MESSENGER);
                 AsyncChannel ac = new AsyncChannel();
                 ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger);
@@ -437,7 +437,7 @@
          */
         for (int retry = 0; retry < 2; retry++) {
             if (mPhoneService == null) {
-                log("Ignoring mobile radio request because could not acquire PhoneService");
+                loge("Ignoring mobile radio request because could not acquire PhoneService");
                 break;
             }
 
@@ -448,7 +448,7 @@
             }
         }
 
-        log("Could not set radio power to " + (turnOn ? "on" : "off"));
+        loge("Could not set radio power to " + (turnOn ? "on" : "off"));
         return false;
     }
 
@@ -457,12 +457,12 @@
      */
     public void setDataEnable(boolean enabled) {
         try {
-            log("setDataEnable: E enabled=" + enabled);
+            if (DBG) log("setDataEnable: E enabled=" + enabled);
             mDataConnectionTrackerAc.sendMessage(DataConnectionTracker.CMD_SET_DATA_ENABLE,
                     enabled ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED);
-            log("setDataEnable: X enabled=" + enabled);
+            if (VDBG) log("setDataEnable: X enabled=" + enabled);
         } catch (Exception e) {
-            log("setDataEnable: X mAc was null" + e);
+            loge("setDataEnable: X mAc was null" + e);
         }
     }
 
@@ -473,15 +473,15 @@
     public void setDependencyMet(boolean met) {
         Bundle bundle = Bundle.forPair(DataConnectionTracker.APN_TYPE_KEY, mApnType);
         try {
-            log("setDependencyMet: E met=" + met);
+            if (DBG) log("setDependencyMet: E met=" + met);
             Message msg = Message.obtain();
             msg.what = DataConnectionTracker.CMD_SET_DEPENDENCY_MET;
             msg.arg1 = (met ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED);
             msg.setData(bundle);
             mDataConnectionTrackerAc.sendMessage(msg);
-            log("setDependencyMet: X met=" + met);
+            if (VDBG) log("setDependencyMet: X met=" + met);
         } catch (NullPointerException e) {
-            log("setDependencyMet: X mAc was null" + e);
+            loge("setDependencyMet: X mAc was null" + e);
         }
     }
 
@@ -508,7 +508,7 @@
          */
         for (int retry = 0; retry < 2; retry++) {
             if (mPhoneService == null) {
-                log("Ignoring feature request because could not acquire PhoneService");
+                loge("Ignoring feature request because could not acquire PhoneService");
                 break;
             }
 
@@ -523,7 +523,7 @@
             }
         }
 
-        log("Could not " + (enable ? "enable" : "disable") + " APN type \"" + apnType + "\"");
+        loge("Could not " + (enable ? "enable" : "disable") + " APN type \"" + apnType + "\"");
         return Phone.APN_REQUEST_FAILED;
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 935281a5..ad76928 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10221,6 +10221,7 @@
             }
 
             canvas.restoreToCount(restoreCount);
+            canvas.setBitmap(null);
 
             if (attachInfo != null) {
                 // Restore the cached Canvas for our siblings
@@ -10289,9 +10290,9 @@
         mPrivateFlags = flags;
 
         canvas.restoreToCount(restoreCount);
+        canvas.setBitmap(null);
 
         if (attachInfo != null) {
-            canvas.setBitmap(null);
             // Restore the cached Canvas for our siblings
             attachInfo.mCanvas = canvas;
         }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index dbcbd6e..9520958 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -220,6 +220,7 @@
     private final int mMaximumDrawingCacheSize;
     private final int mOverscrollDistance;
     private final int mOverflingDistance;
+    private final boolean mFadingMarqueeEnabled;
 
     private boolean sHasPermanentMenuKey;
     private boolean sHasPermanentMenuKeySet;
@@ -246,6 +247,7 @@
         mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE;
         mOverscrollDistance = OVERSCROLL_DISTANCE;
         mOverflingDistance = OVERFLING_DISTANCE;
+        mFadingMarqueeEnabled = true;
     }
 
     /**
@@ -297,6 +299,9 @@
                 sHasPermanentMenuKey = false;
             }
         }
+
+        mFadingMarqueeEnabled = res.getBoolean(
+                com.android.internal.R.bool.config_ui_enableFadingMarquee);
     }
 
     /**
@@ -673,4 +678,12 @@
     public boolean hasPermanentMenuKey() {
         return sHasPermanentMenuKey;
     }
+
+    /**
+     * @hide
+     * @return Whether or not marquee should use fading edges.
+     */
+    public boolean isFadingMarqueeEnabled() {
+        return mFadingMarqueeEnabled;
+    }
 }
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 96e550e..65e72c9 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -1094,6 +1094,9 @@
                             }
 
                             public void post(Object... data) {
+                                if (data[1] != null) {
+                                    ((Canvas) data[1]).setBitmap(null);
+                                }
                                 if (data[0] != null) {
                                     ((Bitmap) data[0]).recycle();
                                 }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index c4ba7c8..4b08f2d 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -1406,6 +1406,7 @@
             v.setTranslationX(translationX);
 
             drawOutline(mCanvas, bitmap);
+            mCanvas.setBitmap(null);
             return bitmap;
         }
 
@@ -1417,6 +1418,7 @@
             dest.drawColor(0, PorterDuff.Mode.CLEAR);
             dest.setMatrix(mIdentityMatrix);
             dest.drawBitmap(mask, xy[0], xy[1], mHolographicPaint);
+            mMaskCanvas.setBitmap(null);
             mask.recycle();
         }
     }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ab66676..65ee745 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -999,7 +999,8 @@
                 setEllipsize(TextUtils.TruncateAt.END);
                 break;
             case 4:
-                setHorizontalFadingEdgeEnabled(true);
+                setHorizontalFadingEdgeEnabled(
+                        ViewConfiguration.get(context).isFadingMarqueeEnabled());
                 setEllipsize(TextUtils.TruncateAt.MARQUEE);
                 break;
         }
@@ -3067,7 +3068,8 @@
 
         if (text instanceof Spanned &&
             ((Spanned) text).getSpanStart(TextUtils.TruncateAt.MARQUEE) >= 0) {
-            setHorizontalFadingEdgeEnabled(true);
+            setHorizontalFadingEdgeEnabled(
+                    ViewConfiguration.get(mContext).isFadingMarqueeEnabled());
             setEllipsize(TextUtils.TruncateAt.MARQUEE);
         }
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 65dce49..73443a0 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -84,6 +84,9 @@
          specified for -large and -xlarge configurations. -->
     <dimen name="config_prefDialogWidth">320dp</dimen>
 
+    <!-- Enables or disables fading edges when marquee is enabled in TextView. -->
+    <bool name="config_ui_enableFadingMarquee">true</bool>
+
     <!-- Whether dialogs should close automatically when the user touches outside
          of them.  This should not normally be modified. -->
     <bool name="config_closeDialogWhenTouchOutside">false</bool>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 40d54bb..3fc6463 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -567,6 +567,7 @@
         
         canvas.setBitmap(bitmap);
         canvas.drawBitmap(source, srcR, dstR, paint);
+        canvas.setBitmap(null);
 
         return bitmap;
     }
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 9bf3de8..9acf99b 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -44,9 +44,11 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Font::Font(FontRenderer* state, uint32_t fontId, float fontSize,
-        int flags, uint32_t italicStyle, uint32_t scaleX) :
+        int flags, uint32_t italicStyle, uint32_t scaleX,
+        SkPaint::Style style, uint32_t strokeWidth) :
         mState(state), mFontId(fontId), mFontSize(fontSize),
-        mFlags(flags), mItalicStyle(italicStyle), mScaleX(scaleX) {
+        mFlags(flags), mItalicStyle(italicStyle), mScaleX(scaleX),
+        mStyle(style), mStrokeWidth(mStrokeWidth) {
 }
 
 
@@ -283,19 +285,22 @@
 }
 
 Font* Font::create(FontRenderer* state, uint32_t fontId, float fontSize,
-        int flags, uint32_t italicStyle, uint32_t scaleX) {
+        int flags, uint32_t italicStyle, uint32_t scaleX,
+        SkPaint::Style style, uint32_t strokeWidth) {
     Vector<Font*> &activeFonts = state->mActiveFonts;
 
     for (uint32_t i = 0; i < activeFonts.size(); i++) {
         Font* font = activeFonts[i];
         if (font->mFontId == fontId && font->mFontSize == fontSize &&
                 font->mFlags == flags && font->mItalicStyle == italicStyle &&
-                font->mScaleX == scaleX) {
+                font->mScaleX == scaleX && font->mStyle == style &&
+                (style == SkPaint::kFill_Style || font->mStrokeWidth == strokeWidth)) {
             return font;
         }
     }
 
-    Font* newFont = new Font(state, fontId, fontSize, flags, italicStyle, scaleX);
+    Font* newFont = new Font(state, fontId, fontSize, flags, italicStyle,
+            scaleX, style, strokeWidth);
     activeFonts.push(newFont);
     return newFont;
 }
@@ -690,7 +695,11 @@
     uint32_t italicStyle = *(uint32_t*) &skewX;
     const float scaleXFloat = paint->getTextScaleX();
     uint32_t scaleX = *(uint32_t*) &scaleXFloat;
-    mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle, scaleX);
+    SkPaint::Style style = paint->getStyle();
+    const float strokeWidthFloat = paint->getStrokeWidth();
+    uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat;
+    mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle,
+            scaleX, style, strokeWidth);
 
     const float maxPrecacheFontSize = 40.0f;
     bool isNewFont = currentNumFonts != mActiveFonts.size();
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 24ed6fa..1922812 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -82,7 +82,8 @@
      * Creates a new font associated with the specified font state.
      */
     static Font* create(FontRenderer* state, uint32_t fontId, float fontSize,
-            int flags, uint32_t italicStyle, uint32_t scaleX);
+            int flags, uint32_t italicStyle, uint32_t scaleX, SkPaint::Style style,
+            uint32_t strokeWidth);
 
 protected:
     friend class FontRenderer;
@@ -128,7 +129,7 @@
     };
 
     Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
-            uint32_t scaleX);
+            uint32_t scaleX, SkPaint::Style style, uint32_t strokeWidth);
 
     // Cache of glyphs
     DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
@@ -157,6 +158,8 @@
     int mFlags;
     uint32_t mItalicStyle;
     uint32_t mScaleX;
+    SkPaint::Style mStyle;
+    uint32_t mStrokeWidth;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 7c181ee..078d4af 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -387,6 +387,7 @@
             if (recycle) {
                 source.recycle();
             }
+            c.setBitmap(null);
             return b2;
         }
         float bitmapWidthF = source.getWidth();
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 6b0fb12..5bfdcdb 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3761,6 +3761,7 @@
             final Canvas canvas = new Canvas(bitmap);
             canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight),
                                           new Rect(0, 0, width, height), sResizePaint);
+            canvas.setBitmap(null);
         }
 
         if (tempBitmap != null) {
@@ -3837,6 +3838,7 @@
                 final Canvas canvas = new Canvas(bitmaps[i]);
                 canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight),
                                               new Rect(0, 0, width, height), sResizePaint);
+                canvas.setBitmap(null);
             }
         }
 
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index 73cc7e2..f0cc1fe 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -1008,6 +1008,7 @@
                                               srcBitmap.getHeight()),
                                               new Rect(0, 0, (int)bitmapWidth,
                                               (int)bitmapHeight), sResizePaint);
+        canvas.setBitmap(null);
         /**
          *  Release the source bitmap
          */
diff --git a/media/java/android/media/videoeditor/OverlayFrame.java b/media/java/android/media/videoeditor/OverlayFrame.java
index 131f5f0..d159df2 100755
--- a/media/java/android/media/videoeditor/OverlayFrame.java
+++ b/media/java/android/media/videoeditor/OverlayFrame.java
@@ -420,6 +420,7 @@
             }
 
             overlayCanvas.drawBitmap(overlayBitmap, srcRect, destRect, sResizePaint);
+            overlayCanvas.setBitmap(null);
 
             /*
              * Write to the dest file
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 3f547fd..4c7f84e 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -1073,6 +1073,15 @@
             return gl;
         }
 
+        public void purgeBuffers() {
+            mEgl.eglMakeCurrent(mEglDisplay,
+                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
+                    EGL10.EGL_NO_CONTEXT);
+            mEgl.eglMakeCurrent(mEglDisplay,
+                    mEglSurface, mEglSurface,
+                    mEglContext);
+        }
+
         /**
          * Display the current render surface.
          * @return false if the context has been lost.
@@ -1415,6 +1424,7 @@
                         if (LOG_RENDERER) {
                             Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")");
                         }
+                        mEglHelper.purgeBuffers();
                         mRenderer.onSurfaceChanged(gl, w, h);
                         sizeChanged = false;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index c896046..d74b548 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -501,6 +501,7 @@
                     new RectF(mGlowBitmapPaddingLeftPx, mGlowBitmapPaddingTopPx,
                             outBitmap.getWidth() - mGlowBitmapPaddingRightPx,
                             outBitmap.getHeight() - mGlowBitmapPaddingBottomPx), paint);
+            canvas.setBitmap(null);
         }
         return outBitmap;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 3a47e6e..fc21929 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -294,6 +294,7 @@
             c.rotate(360f - degrees);
             c.translate(-dims[0] / 2, -dims[1] / 2);
             c.drawBitmap(mScreenBitmap, 0, 0, null);
+            c.setBitmap(null);
             mScreenBitmap = ss;
         }
 
diff --git a/policy/src/com/android/internal/policy/impl/IconUtilities.java b/policy/src/com/android/internal/policy/impl/IconUtilities.java
index 99055cf..4564f90 100644
--- a/policy/src/com/android/internal/policy/impl/IconUtilities.java
+++ b/policy/src/com/android/internal/policy/impl/IconUtilities.java
@@ -186,6 +186,7 @@
         mask.recycle();
 
         dest.drawBitmap(src, 0, 0, mPaint);
+        dest.setBitmap(null);
 
         return result;
     }
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 541a8cf..1bbe934 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -344,7 +344,7 @@
             mPolicyManager.registerListener(mPolicyListener);
         } catch (RemoteException e) {
             // ouch, no rules updates means some processes may never get network
-            Slog.e(TAG, "unable to register INetworkPolicyListener", e);
+            loge("unable to register INetworkPolicyListener" + e.toString());
         }
 
         final PowerManager powerManager = (PowerManager) context.getSystemService(
@@ -798,9 +798,11 @@
         }
 
         public void expire() {
-            log("ConnectivityService FeatureUser expire(" +
-                    mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
-                    (System.currentTimeMillis() - mCreateTime) + " mSec ago");
+            if (VDBG) {
+                log("ConnectivityService FeatureUser expire(" +
+                        mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
+                        (System.currentTimeMillis() - mCreateTime) + " mSec ago");
+            }
             stopUsingNetworkFeature(this, false);
         }
 
@@ -843,7 +845,7 @@
         if(networkType == ConnectivityManager.TYPE_MOBILE) {
             usedNetworkType = convertFeatureToNetworkType(feature);
             if (usedNetworkType < 0) {
-                Slog.e(TAG, "Can't match any netTracker!");
+                loge("Can't match any netTracker!");
                 usedNetworkType = networkType;
             }
         }
@@ -953,7 +955,7 @@
             return stopUsingNetworkFeature(u, true);
         } else {
             // none found!
-            if (DBG) log("ignoring stopUsingNetworkFeature - not a live request");
+            if (VDBG) log("ignoring stopUsingNetworkFeature - not a live request");
             return 1;
         }
     }
@@ -1081,7 +1083,7 @@
 
         if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
                 tracker.isTeardownRequested()) {
-            if (DBG) {
+            if (VDBG) {
                 log("requestRouteToHostAddress on down network " +
                            "(" + networkType + ") - dropped");
             }
@@ -1152,13 +1154,13 @@
             }
         }
         if (doAdd) {
-            if (DBG) log("Adding " + r + " for interface " + ifaceName);
+            if (VDBG) log("Adding " + r + " for interface " + ifaceName);
             mAddedRoutes.add(r);
             try {
                 mNetd.addRoute(ifaceName, r);
             } catch (Exception e) {
                 // never crash - catch them all
-                loge("Exception trying to add a route: " + e);
+                if (VDBG) loge("Exception trying to add a route: " + e);
                 return false;
             }
         } else {
@@ -1166,16 +1168,16 @@
             // we can remove it from the table
             mAddedRoutes.remove(r);
             if (mAddedRoutes.contains(r) == false) {
-                if (DBG) log("Removing " + r + " for interface " + ifaceName);
+                if (VDBG) log("Removing " + r + " for interface " + ifaceName);
                 try {
                     mNetd.removeRoute(ifaceName, r);
                 } catch (Exception e) {
                     // never crash - catch them all
-                    loge("Exception trying to remove a route: " + e);
+                    if (VDBG) loge("Exception trying to remove a route: " + e);
                     return false;
                 }
             } else {
-                if (DBG) log("not removing " + r + " as it's still in use");
+                if (VDBG) log("not removing " + r + " as it's still in use");
             }
         }
         return true;
@@ -1220,7 +1222,7 @@
         enforceAccessPermission();
         boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.MOBILE_DATA, 1) == 1;
-        if (DBG) log("getMobileDataEnabled returning " + retVal);
+        if (VDBG) log("getMobileDataEnabled returning " + retVal);
         return retVal;
     }
 
@@ -1247,7 +1249,7 @@
             mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
             if (LOGD_RULES) {
-                Slog.d(TAG, "onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
+                log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
             }
 
             synchronized (mRulesLock) {
@@ -1268,8 +1270,7 @@
             mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
             if (LOGD_RULES) {
-                Slog.d(TAG,
-                        "onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
+                log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
             }
 
             synchronized (mRulesLock) {
@@ -1294,8 +1295,8 @@
 
     private void handleSetMobileData(boolean enabled) {
         if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
-            if (DBG) {
-                Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
+            if (VDBG) {
+                log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
             }
             mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
         }
@@ -1587,7 +1588,7 @@
                         mNetConfigs[type].priority) ||
                         mNetworkPreference == mActiveDefaultNetwork) {
                         // don't accept this one
-                        if (DBG) {
+                        if (VDBG) {
                             log("Not broadcasting CONNECT_ACTION " +
                                 "to torn down network " + info.getTypeName());
                         }
@@ -1688,9 +1689,11 @@
                     }
                 } else {
                     resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
-                    log("handleConnectivityChange: interface not not equivalent reset both" +
-                            " linkProperty[" + netType + "]:" +
-                            " resetMask=" + resetMask);
+                    if (DBG) {
+                        log("handleConnectivityChange: interface not not equivalent reset both" +
+                                " linkProperty[" + netType + "]:" +
+                                " resetMask=" + resetMask);
+                    }
                 }
             }
             if (mNetConfigs[netType].isDefault()) {
@@ -1798,7 +1801,7 @@
         String bufferSizes = SystemProperties.get(key);
 
         if (bufferSizes.length() == 0) {
-            loge(key + " not found in system properties. Using defaults");
+            if (VDBG) log(key + " not found in system properties. Using defaults");
 
             // Setting to default values so we won't be stuck to previous values
             key = "net.tcp.buffersize.default";
@@ -1807,7 +1810,7 @@
 
         // Set values in kernel
         if (bufferSizes.length() != 0) {
-            if (DBG) {
+            if (VDBG) {
                 log("Setting TCP values: [" + bufferSizes
                         + "] which comes from [" + key + "]");
             }
@@ -1849,7 +1852,7 @@
      */
     private void reassessPidDns(int myPid, boolean doBump)
     {
-        if (DBG) log("reassessPidDns for pid " + myPid);
+        if (VDBG) log("reassessPidDns for pid " + myPid);
         for(int i : mPriorityList) {
             if (mNetConfigs[i].isDefault()) {
                 continue;
@@ -1935,7 +1938,7 @@
             String value = mDefaultDns.getHostAddress();
             if (!value.equals(SystemProperties.get("net.dns1"))) {
                 if (DBG) {
-                    log("no dns provided for " + network + " - using " + value);
+                    loge("no dns provided for " + network + " - using " + value);
                 }
                 changed = true;
                 SystemProperties.set("net.dns1", value);
@@ -1948,7 +1951,7 @@
                 if (!changed && value.equals(SystemProperties.get(key))) {
                     continue;
                 }
-                if (DBG) {
+                if (VDBG) {
                     log("adding dns " + value + " for " + network);
                 }
                 changed = true;
@@ -1957,7 +1960,7 @@
         }
         for (int i = last + 1; i <= mNumDnsEntries; ++i) {
             String key = "net.dns" + i;
-            if (DBG) log("erasing " + key);
+            if (VDBG) log("erasing " + key);
             changed = true;
             SystemProperties.set(key, "");
         }
@@ -1968,7 +1971,7 @@
                 mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
                 mNetd.setDefaultInterfaceForDns(iface);
             } catch (Exception e) {
-                Slog.e(TAG, "exception setting default dns interface: " + e);
+                loge("exception setting default dns interface: " + e);
             }
         }
         if (!domains.equals(SystemProperties.get("net.dns.search"))) {
@@ -1998,7 +2001,7 @@
                     mNetd.setDnsServersForInterface(p.getInterfaceName(),
                             NetworkUtils.makeStrings(dnses));
                 } catch (Exception e) {
-                    Slog.e(TAG, "exception setting dns servers: " + e);
+                    loge("exception setting dns servers: " + e);
                 }
                 // set per-pid dns for attached secondary nets
                 List pids = mNetRequestersPids[netType];
@@ -2335,7 +2338,7 @@
 
     // 100 percent is full good, 0 is full bad.
     public void reportInetCondition(int networkType, int percentage) {
-        if (DBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
+        if (VDBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.STATUS_BAR,
                 "ConnectivityService");
@@ -2372,7 +2375,7 @@
         mDefaultInetCondition = condition;
         int delay;
         if (mInetConditionChangeInFlight == false) {
-            if (DBG) log("starting a change hold");
+            if (VDBG) log("starting a change hold");
             // setup a new hold to debounce this
             if (mDefaultInetCondition > 50) {
                 delay = Settings.Secure.getInt(mContext.getContentResolver(),
@@ -2387,12 +2390,12 @@
         } else {
             // we've set the new condition, when this hold ends that will get
             // picked up
-            if (DBG) log("currently in hold - not setting new end evt");
+            if (VDBG) log("currently in hold - not setting new end evt");
         }
     }
 
     private void handleInetConditionHoldEnd(int netType, int sequence) {
-        if (DBG) {
+        if (VDBG) {
             log("Inet hold end, net=" + netType +
                     ", condition =" + mDefaultInetCondition +
                     ", published condition =" + mDefaultInetConditionPublished);
@@ -2490,7 +2493,7 @@
                 mDefaultProxy = null;
             }
         }
-        if (DBG) log("changing default proxy to " + proxy);
+        if (VDBG) log("changing default proxy to " + proxy);
         if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
         if (mGlobalProxy != null) return;
         sendProxyBroadcast(proxy);
@@ -2517,7 +2520,7 @@
 
     private void sendProxyBroadcast(ProxyProperties proxy) {
         if (proxy == null) proxy = new ProxyProperties("", 0, "");
-        log("sending Proxy Broadcast for " + proxy);
+        if (DBG) log("sending Proxy Broadcast for " + proxy);
         Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
             Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 9cb772e..ecbad099 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -183,7 +183,9 @@
                     android.R.dimen.notification_large_icon_height);
             icon.setBounds(0, 0, width, height);
             bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            icon.draw(new Canvas(bitmap));
+            Canvas c = new Canvas(bitmap);
+            icon.draw(c);
+            c.setBitmap(null);
         }
 
         // Configure the interface. Abort if any of these steps fails.
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 88e0fa8..3d977d0 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -3326,7 +3326,7 @@
         if (pkg.applicationInfo.nativeLibraryDir != null) {
             try {
                 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
-                final String dataPathString = dataPath.getCanonicalFile().getPath();
+                final String dataPathString = dataPath.getCanonicalPath();
 
                 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
                     /*
@@ -3340,7 +3340,7 @@
                         Log.i(TAG, "removed obsolete native libraries for system package "
                                 + path);
                     }
-                } else if (nativeLibraryDir.getCanonicalFile().getParent()
+                } else if (nativeLibraryDir.getParentFile().getCanonicalPath()
                         .equals(dataPathString)) {
                     /*
                      * Make sure the native library dir isn't a symlink to
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index f8059f5..e0b5e17 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -4919,6 +4919,7 @@
         matrix.postTranslate(-(int)(frame.left*scale), -(int)(frame.top*scale));
         Canvas canvas = new Canvas(bm);
         canvas.drawBitmap(rawss, matrix, null);
+        canvas.setBitmap(null);
 
         rawss.recycle();
         return bm;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 7bf3e0a..f4be168 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -40,6 +40,7 @@
 
 #include "GLExtensions.h"
 #include "HWComposer.h"
+#include "SurfaceFlinger.h"
 
 using namespace android;
 
@@ -75,7 +76,7 @@
         const sp<SurfaceFlinger>& flinger,
         uint32_t dpy)
     : DisplayHardwareBase(flinger, dpy),
-      mFlags(0), mHwc(0)
+      mFlinger(flinger), mFlags(0), mHwc(0)
 {
     init(dpy);
 }
@@ -310,7 +311,7 @@
 
 
     // initialize the H/W composer
-    mHwc = new HWComposer();
+    mHwc = new HWComposer(mFlinger);
     if (mHwc->initCheck() == NO_ERROR) {
         mHwc->setFrameBuffer(mDisplay, mSurface);
     }
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index cdf89fd..40a6f1e 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -95,6 +95,7 @@
     void init(uint32_t displayIndex) __attribute__((noinline));
     void fini() __attribute__((noinline));
 
+    sp<SurfaceFlinger> mFlinger;
     EGLDisplay      mDisplay;
     EGLSurface      mSurface;
     EGLContext      mContext;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index 30eb258..3ebc7b6 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -37,7 +37,7 @@
 
                 ~DisplayHardwareBase();
 
-    // console managment
+    // console management
     void releaseScreen() const;
     void acquireScreen() const;
     bool isScreenAcquired() const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 4a3b20d..7d1bdf0 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -30,12 +30,14 @@
 #include <EGL/egl.h>
 
 #include "HWComposer.h"
+#include "SurfaceFlinger.h"
 
 namespace android {
 // ---------------------------------------------------------------------------
 
-HWComposer::HWComposer()
-    : mModule(0), mHwc(0), mList(0), mCapacity(0),
+HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
+    : mFlinger(flinger),
+      mModule(0), mHwc(0), mList(0), mCapacity(0),
       mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
 {
     int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
@@ -44,6 +46,13 @@
         err = hwc_open(mModule, &mHwc);
         LOGE_IF(err, "%s device failed to initialize (%s)",
                 HWC_HARDWARE_COMPOSER, strerror(-err));
+        if (err == 0) {
+            if (mHwc->registerProcs) {
+                mCBContext.hwc = this;
+                mCBContext.procs.invalidate = &hook_invalidate;
+                mHwc->registerProcs(mHwc, &mCBContext.procs);
+            }
+        }
     }
 }
 
@@ -58,6 +67,14 @@
     return mHwc ? NO_ERROR : NO_INIT;
 }
 
+void HWComposer::hook_invalidate(struct hwc_procs* procs) {
+    reinterpret_cast<cb_context *>(procs)->hwc->invalidate();
+}
+
+void HWComposer::invalidate() {
+    mFlinger->signalEvent();
+}
+
 void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
     mDpy = (hwc_display_t)dpy;
     mSur = (hwc_surface_t)sur;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 5a9e9eb..983898a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -24,16 +24,19 @@
 
 #include <hardware/hwcomposer.h>
 
+#include <utils/StrongPointer.h>
+
 namespace android {
 // ---------------------------------------------------------------------------
 
 class String8;
+class SurfaceFlinger;
 
 class HWComposer
 {
 public:
 
-    HWComposer();
+    HWComposer(const sp<SurfaceFlinger>& flinger);
     ~HWComposer();
 
     status_t initCheck() const;
@@ -60,12 +63,21 @@
     void dump(String8& out, char* scratch, size_t SIZE) const;
 
 private:
+    struct cb_context {
+        hwc_procs_t procs;
+        HWComposer* hwc;
+    };
+    static void hook_invalidate(struct hwc_procs* procs);
+    void invalidate();
+
+    sp<SurfaceFlinger>      mFlinger;
     hw_module_t const*      mModule;
     hwc_composer_device_t*  mHwc;
     hwc_layer_list_t*       mList;
     size_t                  mCapacity;
     hwc_display_t           mDpy;
     hwc_surface_t           mSur;
+    cb_context              mCBContext;
 };
 
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 886bb2a..383c045 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -172,17 +172,14 @@
 
 void Layer::setGeometry(hwc_layer_t* hwcl)
 {
-    hwcl->compositionType = HWC_FRAMEBUFFER;
-    hwcl->hints = 0;
-    hwcl->flags = 0;
-    hwcl->transform = 0;
-    hwcl->blending = HWC_BLENDING_NONE;
+    LayerBaseClient::setGeometry(hwcl);
+
+    hwcl->flags &= ~HWC_SKIP_LAYER;
 
     // we can't do alpha-fade with the hwc HAL
     const State& s(drawingState());
     if (s.alpha < 0xFF) {
         hwcl->flags = HWC_SKIP_LAYER;
-        return;
     }
 
     /*
@@ -205,26 +202,9 @@
     // we can only handle simple transformation
     if (finalTransform & Transform::ROT_INVALID) {
         hwcl->flags = HWC_SKIP_LAYER;
-        return;
+    } else {
+        hwcl->transform = finalTransform;
     }
-
-    hwcl->transform = finalTransform;
-
-    if (!isOpaque()) {
-        hwcl->blending = mPremultipliedAlpha ?
-                HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
-    }
-
-    // scaling is already applied in mTransformedBounds
-    hwcl->displayFrame.left   = mTransformedBounds.left;
-    hwcl->displayFrame.top    = mTransformedBounds.top;
-    hwcl->displayFrame.right  = mTransformedBounds.right;
-    hwcl->displayFrame.bottom = mTransformedBounds.bottom;
-
-    hwcl->visibleRegionScreen.rects =
-            reinterpret_cast<hwc_rect_t const *>(
-                    visibleRegionScreen.getArray(
-                            &hwcl->visibleRegionScreen.numRects));
 }
 
 void Layer::setPerFrameData(hwc_layer_t* hwcl) {
@@ -235,9 +215,9 @@
         // HWC handle it.
         hwcl->flags |= HWC_SKIP_LAYER;
         hwcl->handle = NULL;
-        return;
+    } else {
+        hwcl->handle = buffer->handle;
     }
-    hwcl->handle = buffer->handle;
 
     if (isCropped()) {
         hwcl->sourceCrop.left   = mCurrentCrop.left;
@@ -247,8 +227,13 @@
     } else {
         hwcl->sourceCrop.left   = 0;
         hwcl->sourceCrop.top    = 0;
-        hwcl->sourceCrop.right  = buffer->width;
-        hwcl->sourceCrop.bottom = buffer->height;
+        if (buffer != NULL) {
+            hwcl->sourceCrop.right  = buffer->width;
+            hwcl->sourceCrop.bottom = buffer->height;
+        } else {
+            hwcl->sourceCrop.right  = mTransformedBounds.width();
+            hwcl->sourceCrop.bottom = mTransformedBounds.height();
+        }
     }
 }
 
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index c86c659..e04c533 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -302,13 +302,47 @@
     }
 }
 
-void LayerBase::setGeometry(hwc_layer_t* hwcl) {
-    hwcl->flags |= HWC_SKIP_LAYER;
+void LayerBase::setGeometry(hwc_layer_t* hwcl)
+{
+    hwcl->compositionType = HWC_FRAMEBUFFER;
+    hwcl->hints = 0;
+    hwcl->flags = HWC_SKIP_LAYER;
+    hwcl->transform = 0;
+    hwcl->blending = HWC_BLENDING_NONE;
+
+    // this gives us only the "orientation" component of the transform
+    const State& s(drawingState());
+    const uint32_t finalTransform = s.transform.getOrientation();
+    // we can only handle simple transformation
+    if (finalTransform & Transform::ROT_INVALID) {
+        hwcl->flags = HWC_SKIP_LAYER;
+    } else {
+        hwcl->transform = finalTransform;
+    }
+
+    if (!isOpaque()) {
+        hwcl->blending = mPremultipliedAlpha ?
+                HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
+    }
+
+    // scaling is already applied in mTransformedBounds
+    hwcl->displayFrame.left   = mTransformedBounds.left;
+    hwcl->displayFrame.top    = mTransformedBounds.top;
+    hwcl->displayFrame.right  = mTransformedBounds.right;
+    hwcl->displayFrame.bottom = mTransformedBounds.bottom;
+    hwcl->visibleRegionScreen.rects =
+            reinterpret_cast<hwc_rect_t const *>(
+                    visibleRegionScreen.getArray(
+                            &hwcl->visibleRegionScreen.numRects));
 }
 
 void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
     hwcl->compositionType = HWC_FRAMEBUFFER;
     hwcl->handle = NULL;
+    hwcl->sourceCrop.left   = 0;
+    hwcl->sourceCrop.top    = 0;
+    hwcl->sourceCrop.right  = mTransformedBounds.width();
+    hwcl->sourceCrop.bottom = mTransformedBounds.height();
 }
 
 void LayerBase::setFiltering(bool filtering)
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
index 7bf25cf..4037a69 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
@@ -77,13 +77,23 @@
             super.onDraw(canvas);
             canvas.drawRGB(255, 255, 255);
 
+            mMediumPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+            mMediumPaint.setStrokeWidth(2.0f);
             canvas.drawText("Hello OpenGL renderer!", 100, 20, mMediumPaint);
+
+            mMediumPaint.setStyle(Paint.Style.FILL);
             mMediumPaint.setTextAlign(Paint.Align.CENTER);
             canvas.drawText("Hello OpenGL renderer!", 100, 40, mMediumPaint);
+
+            mMediumPaint.setStyle(Paint.Style.STROKE);
+            mMediumPaint.setStrokeWidth(2.0f);
             mMediumPaint.setTextAlign(Paint.Align.RIGHT);
             canvas.drawText("Hello OpenGL renderer!", 100, 60, mMediumPaint);
+
+            mMediumPaint.setStyle(Paint.Style.FILL);
             mMediumPaint.setTextAlign(Paint.Align.LEFT);
             canvas.drawText("Hello OpenGL renderer!", 100, 100, mMediumPaint);
+
             mMediumPaint.setShadowLayer(2.5f, 0.0f, 0.0f, 0xff000000);
             canvas.drawText("Hello OpenGL renderer!", 100, 150, mMediumPaint);
             mMediumPaint.clearShadowLayer();