LayoutLib fixes for N

Moves LayoutLib to Java 8 - YAY!
Fix delegates

Change-Id: I098996e43e330e995d33f12df1c16355bbc02f0f
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 1d6e52c..05fd4c8 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -69,10 +69,8 @@
     private static final int[] ATTRS_TEXT_COLOR = new int[] {R.attr.textColor};
     private static final int[] ATTRS_DISABLED_ALPHA = new int[] {R.attr.disabledAlpha};
 
-    // LayoutLib relies on these constants. Change TimePickerClockDelegate_Delegate if
-    // modifying these.
-    static final int AM = 0;
-    static final int PM = 1;
+    private static final int AM = 0;
+    private static final int PM = 1;
 
     private static final int HOURS_IN_HALF_DAY = 12;
 
diff --git a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
index 5bb3e3e..3681f2a 100644
--- a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
+++ b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <component name="InspectionProjectProfileManager">
   <profile version="1.0" is_locked="false">
     <option name="myName" value="Project Default" />
@@ -8,6 +7,15 @@
       <option name="CHECK_TRY_CATCH_SECTION" value="true" />
       <option name="CHECK_METHOD_BODY" value="true" />
     </inspection_tool>
+    <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
+      <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
+    </inspection_tool>
     <inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="false" />
+      <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" />
+      <option name="SUGGEST_PRIVATE_FOR_INNERS" value="true" />
+    </inspection_tool>
   </profile>
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/misc.xml b/tools/layoutlib/.idea/misc.xml
index b474bdc..44b47f2 100644
--- a/tools/layoutlib/.idea/misc.xml
+++ b/tools/layoutlib/.idea/misc.xml
@@ -37,7 +37,7 @@
       </value>
     </option>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
 </project>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml b/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml
index 4f0eb8d..b402849 100644
--- a/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml
@@ -26,4 +26,4 @@
     <ConfigurationWrapper RunnerId="Run" />
     <method />
   </configuration>
-</component>
\ No newline at end of file
+</component>
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 53bfc15..5e57a25 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -16,8 +16,6 @@
 LOCAL_PATH := $(my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_JAVACFLAGS := -source 6 -target 6
-
 #
 # Define rules to build temp_layoutlib.jar, which contains a subset of
 # the classes in framework.jar.  The layoutlib_create tool is used to
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 0dbdd56..3dd8002 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -18,8 +18,6 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_JAVA_RESOURCE_DIRS := resources
-LOCAL_JAVACFLAGS := -source 6 -target 6
-
 
 LOCAL_JAVA_LIBRARIES := \
 	layoutlib_api-prebuilt \
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index 0e39243..fe46480 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -49,6 +49,7 @@
 import java.io.InputStream;
 import java.util.Iterator;
 
+@SuppressWarnings("deprecation")
 public final class BridgeResources extends Resources {
 
     private BridgeContext mContext;
@@ -70,6 +71,7 @@
 
         @Override
         public boolean markSupported() {
+            //noinspection SimplifiableIfStatement
             if (mFakeMarkSupport) {
                 // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
                 return true;
@@ -595,7 +597,6 @@
         if (value != null) {
             ResourceValue resValue = value.getSecond();
 
-            assert resValue != null;
             if (resValue != null) {
                 String v = resValue.getValue();
                 if (v != null) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 0737682..e3bb3e3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -17,9 +17,14 @@
 package android.graphics;
 
 import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.RenderAction;
 import com.android.resources.Density;
+import com.android.resources.ResourceType;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
 import android.annotation.Nullable;
@@ -38,6 +43,7 @@
 import java.util.Set;
 
 import javax.imageio.ImageIO;
+import libcore.util.NativeAllocationRegistry_Delegate;
 
 /**
  * Delegate implementing the native methods of android.graphics.Bitmap
@@ -62,12 +68,13 @@
     // ---- delegate manager ----
     private static final DelegateManager<Bitmap_Delegate> sManager =
             new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class);
+    private static long sFinalizer = -1;
 
     // ---- delegate helper data ----
 
     // ---- delegate data ----
     private final Config mConfig;
-    private BufferedImage mImage;
+    private final BufferedImage mImage;
     private boolean mHasAlpha = true;
     private boolean mHasMipMap = false;      // TODO: check the default.
     private boolean mIsPremultiplied = true;
@@ -114,10 +121,25 @@
      * @see Bitmap#isMutable()
      * @see Bitmap#getDensity()
      */
-    public static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
+    private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
             Density density) throws IOException {
         // create a delegate with the content of the file.
-        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
+        BufferedImage image = ImageIO.read(input);
+        if (image == null && input.exists()) {
+            // There was a problem decoding the image, or the decoder isn't registered. Webp maybe.
+            // Replace with a broken image icon.
+            BridgeContext currentContext = RenderAction.getCurrentContext();
+            if (currentContext != null) {
+                RenderResources resources = currentContext.getRenderResources();
+                ResourceValue broken = resources.getFrameworkResource(ResourceType.DRAWABLE,
+                        "ic_menu_report_image");
+                File brokenFile = new File(broken.getValue());
+                if (brokenFile.exists()) {
+                    image = ImageIO.read(brokenFile);
+                }
+            }
+        }
+        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
 
         return createBitmap(delegate, createFlags, density.getDpiValue());
     }
@@ -281,8 +303,13 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeDestructor(long nativeBitmap) {
-        sManager.removeJavaReferenceFor(nativeBitmap);
+    /*package*/ static long nativeGetNativeFinalizer() {
+        synchronized (Bitmap_Delegate.class) {
+            if (sFinalizer == -1) {
+                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
+            }
+            return sFinalizer;
+        }
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index ba0d399..c4fbd56 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -21,6 +21,7 @@
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.layoutlib.bridge.impl.GcSnapshot;
 import com.android.layoutlib.bridge.impl.PorterDuffUtility;
+import com.android.ninepatch.NinePatchChunk;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
 import android.annotation.Nullable;
@@ -38,6 +39,8 @@
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 
+import libcore.util.NativeAllocationRegistry_Delegate;
+
 
 /**
  * Delegate implementing the native methods of android.graphics.Canvas
@@ -57,6 +60,7 @@
     // ---- delegate manager ----
     private static final DelegateManager<Canvas_Delegate> sManager =
             new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class);
+    private static long sFinalizer = -1;
 
 
     // ---- delegate helper data ----
@@ -160,6 +164,9 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
+
+    @LayoutlibDelegate
     /*package*/ static int native_getWidth(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -749,6 +756,61 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static void native_drawRegion(long nativeCanvas, long nativeRegion,
+            long nativePaint) {
+        // FIXME
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+                "Some canvas paths may not be drawn", null, null);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
+            long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
+            final float dstRight, final float dstBottom, long nativePaintOrZero,
+            final int screenDensity, final int bitmapDensity) {
+
+        // get the delegate from the native int.
+        final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap);
+        if (bitmapDelegate == null) {
+            return;
+        }
+
+        byte[] c = NinePatch_Delegate.getChunk(ninePatch);
+        if (c == null) {
+            // not a 9-patch?
+            BufferedImage image = bitmapDelegate.getImage();
+            drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(),
+                    image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight,
+                    (int) dstBottom);
+            return;
+        }
+
+        final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c);
+        assert chunkObject != null;
+        if (chunkObject == null) {
+            return;
+        }
+
+        Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        // this one can be null
+        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
+
+        canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
+            @Override
+            public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop,
+                        (int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity,
+                        bitmapDensity);
+            }
+        }, paintDelegate, true, false);
+
+    }
+
+    @LayoutlibDelegate
     /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
                                                  float left, float top,
                                                  long nativePaintOrZero,
@@ -934,20 +996,21 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void finalizer(long nativeCanvas) {
-        // get the delegate from the native int so that it can be disposed.
-        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
-        if (canvasDelegate == null) {
-            return;
+    /*package*/ static long getNativeFinalizer() {
+        synchronized (Canvas_Delegate.class) {
+            if (sFinalizer == -1) {
+                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(nativePtr -> {
+                    Canvas_Delegate delegate = sManager.getDelegate(nativePtr);
+                    if (delegate != null) {
+                        delegate.dispose();
+                    }
+                    sManager.removeJavaReferenceFor(nativePtr);
+                });
+            }
         }
-
-        canvasDelegate.dispose();
-
-        // remove it from the manager.
-        sManager.removeJavaReferenceFor(nativeCanvas);
+        return sFinalizer;
     }
 
-
     // ---- Private delegate/helper methods ----
 
     /**
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index b6588b6..0e66baa 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -33,13 +33,13 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Scanner;
 import java.util.Set;
 
@@ -213,7 +213,7 @@
         return mValid;
     }
 
-    /*package*/ static Font loadFont(String path) {
+    private static Font loadFont(String path) {
         if (path.startsWith(SYSTEM_FONTS) ) {
             String relativePath = path.substring(SYSTEM_FONTS.length());
             File f = new File(sFontLocation, relativePath);
@@ -270,16 +270,12 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean nAddFont(long nativeFamily, final String path) {
+    /*package*/ static boolean nAddFont(long nativeFamily, final String path, int ttcIndex) {
+        // FIXME: support ttc fonts. Hack JRE??
         final FontFamily_Delegate delegate = getDelegate(nativeFamily);
         if (delegate != null) {
             if (sFontLocation == null) {
-                delegate.mPostInitRunnables.add(new Runnable() {
-                    @Override
-                    public void run() {
-                        delegate.addFont(path);
-                    }
-                });
+                delegate.mPostInitRunnables.add(() -> delegate.addFont(path));
                 return true;
             }
             return delegate.addFont(path);
@@ -289,18 +285,18 @@
 
     @LayoutlibDelegate
     /*package*/ static boolean nAddFontWeightStyle(long nativeFamily,
-            final String path, final int index, final List<FontListParser.Axis> axes,
+            ByteBuffer buffer, final List<FontListParser.Axis> axes,
             final int weight, final boolean isItalic) {
-        // 'index' and 'axes' are not supported by java.awt.Font
+        assert false : "The only client of this method has been overriden.";
+        return false;
+    }
+
+    static boolean addFont(long nativeFamily, final String path, final int weight,
+            final boolean isItalic) {
         final FontFamily_Delegate delegate = getDelegate(nativeFamily);
         if (delegate != null) {
             if (sFontLocation == null) {
-                delegate.mPostInitRunnables.add(new Runnable() {
-                    @Override
-                    public void run() {
-                        delegate.addFont(path, weight, isItalic);
-                    }
-                });
+                delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, isItalic));
                 return true;
             }
             return delegate.addFont(path, weight, isItalic);
@@ -311,6 +307,9 @@
     @LayoutlibDelegate
     /*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
         FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily);
+        if (ffd == null) {
+            return false;
+        }
         ffd.mValid = true;
         if (mgr == null) {
             return false;
@@ -454,6 +453,7 @@
     private FontInfo deriveFont(@NonNull FontInfo srcFont, @NonNull FontInfo outFont) {
         int desiredWeight = outFont.mWeight;
         int srcWeight = srcFont.mWeight;
+        assert srcFont.mFont != null;
         Font derivedFont = srcFont.mFont;
         // Embolden the font if required.
         if (desiredWeight >= BOLD_FONT_WEIGHT && desiredWeight - srcWeight > BOLD_FONT_WEIGHT_DELTA / 2) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index e8d34d0..1f0eb3b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -169,77 +169,18 @@
         sManager.removeJavaReferenceFor(chunk);
     }
 
-    @LayoutlibDelegate
-    /*package*/ static void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance,
-            long chunk, long paint_instance_or_null, int destDensity, int srcDensity) {
-        draw(canvas_instance,
-                (int) loc.left, (int) loc.top, (int) loc.right, (int) loc.bottom,
-                bitmap_instance, chunk, paint_instance_or_null,
-                destDensity, srcDensity);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance,
-            long chunk, long paint_instance_or_null, int destDensity, int srcDensity) {
-        draw(canvas_instance,
-                loc.left, loc.top, loc.right, loc.bottom,
-                bitmap_instance, chunk, paint_instance_or_null,
-                destDensity, srcDensity);
-    }
 
     @LayoutlibDelegate
     /*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) {
         return 0;
     }
 
-    // ---- Private Helper methods ----
-
-    private static void draw(long canvas_instance,
-            final int left, final int top, final int right, final int bottom,
-            Bitmap bitmap_instance, long chunk, long paint_instance_or_null,
-            final int destDensity, final int srcDensity) {
-        // get the delegate from the native int.
-        final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance);
-        if (bitmap_delegate == null) {
-            return;
-        }
-
-        byte[] c = null;
-        NinePatch_Delegate delegate = sManager.getDelegate(chunk);
+    static byte[] getChunk(long nativeNinePatch) {
+        NinePatch_Delegate delegate = sManager.getDelegate(nativeNinePatch);
         if (delegate != null) {
-            c = delegate.chunk;
+            return delegate.chunk;
         }
-        if (c == null) {
-            // not a 9-patch?
-            BufferedImage image = bitmap_delegate.getImage();
-            Canvas_Delegate.native_drawBitmap(null, canvas_instance, bitmap_instance,
-                    0f, 0f, (float)image.getWidth(), (float)image.getHeight(),
-                    (float)left, (float)top, (float)right, (float)bottom,
-                    paint_instance_or_null, destDensity, srcDensity);
-            return;
-        }
+        return null;
+    }
 
-        final NinePatchChunk chunkObject = getChunk(c);
-        assert chunkObject != null;
-        if (chunkObject == null) {
-            return;
-        }
-
-        Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance);
-        if (canvas_delegate == null) {
-            return;
-        }
-
-        // this one can be null
-        Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null);
-
-        canvas_delegate.getSnapshot().draw(new GcSnapshot.Drawable() {
-                @Override
-                public void draw(Graphics2D graphics, Paint_Delegate paint) {
-                    chunkObject.draw(bitmap_delegate.getImage(), graphics,
-                            left, top, right - left, bottom - top, destDensity, srcDensity);
-                }
-            }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/);
-
-     }
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index dbd45c4..514d785 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -39,6 +39,8 @@
 import java.util.List;
 import java.util.Locale;
 
+import libcore.util.NativeAllocationRegistry_Delegate;
+
 /**
  * Delegate implementing the native methods of android.graphics.Paint
  *
@@ -65,6 +67,7 @@
     // ---- delegate manager ----
     private static final DelegateManager<Paint_Delegate> sManager =
             new DelegateManager<Paint_Delegate>(Paint_Delegate.class);
+    private static long sFinalizer = -1;
 
     // ---- delegate helper data ----
 
@@ -250,9 +253,9 @@
     // ---- native methods ----
 
     @LayoutlibDelegate
-    /*package*/ static int getFlags(Paint thisPaint) {
+    /*package*/ static int nGetFlags(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
         }
@@ -263,9 +266,9 @@
 
 
     @LayoutlibDelegate
-    /*package*/ static void setFlags(Paint thisPaint, int flags) {
+    /*package*/ static void nSetFlags(Paint thisPaint, long nativePaint, int flags) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -274,14 +277,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
-        setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
+    /*package*/ static void nSetFilterBitmap(Paint thisPaint, long nativePaint, boolean filter) {
+        setFlag(nativePaint, Paint.FILTER_BITMAP_FLAG, filter);
     }
 
     @LayoutlibDelegate
-    /*package*/ static int getHinting(Paint thisPaint) {
+    /*package*/ static int nGetHinting(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return Paint.HINTING_ON;
         }
@@ -290,9 +293,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setHinting(Paint thisPaint, int mode) {
+    /*package*/ static void nSetHinting(Paint thisPaint, long nativePaint, int mode) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -301,44 +304,48 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
-        setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa);
+    /*package*/ static void nSetAntiAlias(Paint thisPaint, long nativePaint, boolean aa) {
+        setFlag(nativePaint, Paint.ANTI_ALIAS_FLAG, aa);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) {
-        setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
+    /*package*/ static void nSetSubpixelText(Paint thisPaint, long nativePaint,
+            boolean subpixelText) {
+        setFlag(nativePaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) {
-        setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
+    /*package*/ static void nSetUnderlineText(Paint thisPaint, long nativePaint,
+            boolean underlineText) {
+        setFlag(nativePaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) {
-        setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
+    /*package*/ static void nSetStrikeThruText(Paint thisPaint, long nativePaint,
+            boolean strikeThruText) {
+        setFlag(nativePaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) {
-        setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
+    /*package*/ static void nSetFakeBoldText(Paint thisPaint, long nativePaint,
+            boolean fakeBoldText) {
+        setFlag(nativePaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setDither(Paint thisPaint, boolean dither) {
-        setFlag(thisPaint, Paint.DITHER_FLAG, dither);
+    /*package*/ static void nSetDither(Paint thisPaint, long nativePaint, boolean dither) {
+        setFlag(nativePaint, Paint.DITHER_FLAG, dither);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) {
-        setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText);
+    /*package*/ static void nSetLinearText(Paint thisPaint, long nativePaint, boolean linearText) {
+        setFlag(nativePaint, Paint.LINEAR_TEXT_FLAG, linearText);
     }
 
     @LayoutlibDelegate
-    /*package*/ static int getColor(Paint thisPaint) {
+    /*package*/ static int nGetColor(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
         }
@@ -347,9 +354,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setColor(Paint thisPaint, int color) {
+    /*package*/ static void nSetColor(Paint thisPaint, long nativePaint, int color) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -358,9 +365,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int getAlpha(Paint thisPaint) {
+    /*package*/ static int nGetAlpha(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
         }
@@ -369,9 +376,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setAlpha(Paint thisPaint, int a) {
+    /*package*/ static void nSetAlpha(Paint thisPaint, long nativePaint, int a) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -380,9 +387,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float getStrokeWidth(Paint thisPaint) {
+    /*package*/ static float nGetStrokeWidth(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 1.f;
         }
@@ -391,9 +398,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
+    /*package*/ static void nSetStrokeWidth(Paint thisPaint, long nativePaint, float width) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -402,9 +409,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float getStrokeMiter(Paint thisPaint) {
+    /*package*/ static float nGetStrokeMiter(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 1.f;
         }
@@ -413,9 +420,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
+    /*package*/ static void nSetStrokeMiter(Paint thisPaint, long nativePaint, float miter) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -424,7 +431,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setShadowLayer(long paint, float radius, float dx, float dy,
+    /*package*/ static void nSetShadowLayer(long paint, float radius, float dx, float dy,
             int color) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -432,7 +439,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_hasShadowLayer(long paint) {
+    /*package*/ static boolean nHasShadowLayer(long paint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                 "Paint.hasShadowLayer is not supported.", null, null /*data*/);
@@ -440,16 +447,17 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
+    /*package*/ static boolean nIsElegantTextHeight(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT;
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
+    /*package*/ static void nSetElegantTextHeight(Paint thisPaint, long nativePaint,
+            boolean elegant) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -458,9 +466,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float getTextSize(Paint thisPaint) {
+    /*package*/ static float nGetTextSize(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 1.f;
         }
@@ -469,9 +477,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setTextSize(Paint thisPaint, float textSize) {
+    /*package*/ static void nSetTextSize(Paint thisPaint, long nativePaint, float textSize) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -483,9 +491,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float getTextScaleX(Paint thisPaint) {
+    /*package*/ static float nGetTextScaleX(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 1.f;
         }
@@ -494,9 +502,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
+    /*package*/ static void nSetTextScaleX(Paint thisPaint, long nativePaint, float scaleX) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -508,9 +516,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float getTextSkewX(Paint thisPaint) {
+    /*package*/ static float nGetTextSkewX(Paint thisPaint, long nativePaint) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 1.f;
         }
@@ -519,9 +527,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
+    /*package*/ static void nSetTextSkewX(Paint thisPaint, long nativePaint, float skewX) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
@@ -533,9 +541,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float ascent(Paint thisPaint) {
+    /*package*/ static float nAscent(Paint thisPaint, long nativePaint, long nativeTypeface) {
         // get the delegate
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
         }
@@ -550,9 +558,9 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float descent(Paint thisPaint) {
+    /*package*/ static float nDescent(Paint thisPaint, long nativePaint, long nativeTypeface) {
         // get the delegate
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
         }
@@ -567,9 +575,10 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
+    /*package*/ static float nGetFontMetrics(Paint thisPaint, long nativePaint, long nativeTypeface,
+            FontMetrics metrics) {
         // get the delegate
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
         }
@@ -578,9 +587,10 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
+    /*package*/ static int nGetFontMetricsInt(Paint thisPaint, long nativePaint,
+            long nativeTypeface, FontMetricsInt fmi) {
         // get the delegate
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
         }
@@ -603,31 +613,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
-            int count, int bidiFlags) {
-        // get the delegate
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
-        if (delegate == null) {
-            return 0;
-        }
-
-        RectF bounds = delegate.measureText(text, index, count, null, 0, bidiFlags);
-        return bounds.right - bounds.left;
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end,
-        int bidiFlags) {
-        return native_measureText(thisPaint, text.toCharArray(), start, end - start, bidiFlags);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static float native_measureText(Paint thisPaint, String text, int bidiFlags) {
-        return native_measureText(thisPaint, text.toCharArray(), 0, text.length(), bidiFlags);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, char[] text,
+    /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, char[] text,
             int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) {
 
         // get the delegate
@@ -669,21 +655,21 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, String text,
+    /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, String text,
             boolean measureForwards,
             float maxWidth, int bidiFlags, float[] measuredWidth) {
-        return native_breakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
+        return nBreakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
                 maxWidth, bidiFlags, measuredWidth);
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_init() {
+    /*package*/ static long nInit() {
         Paint_Delegate newDelegate = new Paint_Delegate();
         return sManager.addNewDelegate(newDelegate);
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_initWithPaint(long paint) {
+    /*package*/ static long nInitWithPaint(long paint) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(paint);
         if (delegate == null) {
@@ -695,7 +681,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_reset(long native_object) {
+    /*package*/ static void nReset(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -706,7 +692,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_set(long native_dst, long native_src) {
+    /*package*/ static void nSet(long native_dst, long native_src) {
         // get the delegate from the native int.
         Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
         if (delegate_dst == null) {
@@ -723,7 +709,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getStyle(long native_object) {
+    /*package*/ static int nGetStyle(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -734,7 +720,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setStyle(long native_object, int style) {
+    /*package*/ static void nSetStyle(long native_object, int style) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -745,7 +731,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getStrokeCap(long native_object) {
+    /*package*/ static int nGetStrokeCap(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -756,7 +742,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setStrokeCap(long native_object, int cap) {
+    /*package*/ static void nSetStrokeCap(long native_object, int cap) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -767,7 +753,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getStrokeJoin(long native_object) {
+    /*package*/ static int nGetStrokeJoin(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -778,7 +764,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setStrokeJoin(long native_object, int join) {
+    /*package*/ static void nSetStrokeJoin(long native_object, int join) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -789,7 +775,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_getFillPath(long native_object, long src, long dst) {
+    /*package*/ static boolean nGetFillPath(long native_object, long src, long dst) {
         Paint_Delegate paint = sManager.getDelegate(native_object);
         if (paint == null) {
             return false;
@@ -815,7 +801,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_setShader(long native_object, long shader) {
+    /*package*/ static long nSetShader(long native_object, long shader) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -828,7 +814,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_setColorFilter(long native_object, long filter) {
+    /*package*/ static long nSetColorFilter(long native_object, long filter) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -847,7 +833,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_setXfermode(long native_object, long xfermode) {
+    /*package*/ static long nSetXfermode(long native_object, long xfermode) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -860,7 +846,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_setPathEffect(long native_object, long effect) {
+    /*package*/ static long nSetPathEffect(long native_object, long effect) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -873,7 +859,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_setMaskFilter(long native_object, long maskfilter) {
+    /*package*/ static long nSetMaskFilter(long native_object, long maskfilter) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -892,7 +878,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_setTypeface(long native_object, long typeface) {
+    /*package*/ static long nSetTypeface(long native_object, long typeface) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -909,7 +895,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_setRasterizer(long native_object, long rasterizer) {
+    /*package*/ static long nSetRasterizer(long native_object, long rasterizer) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -928,7 +914,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getTextAlign(long native_object) {
+    /*package*/ static int nGetTextAlign(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -939,7 +925,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setTextAlign(long native_object, int align) {
+    /*package*/ static void nSetTextAlign(long native_object, int align) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -950,58 +936,27 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setTextLocale(long native_object, String locale) {
-        // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(native_object);
-        if (delegate == null) {
-            return;
-        }
-
-        delegate.setTextLocale(locale);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static int native_getTextWidths(long native_object, long native_typeface,
-            char[] text, int index, int count, int bidiFlags, float[] widths) {
-
-        if (widths != null) {
-            for (int i = 0; i< count; i++) {
-                widths[i]=0;
-            }
-        }
+    /*package*/ static int nSetTextLocales(long native_object, String locale) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
             return 0;
         }
 
-        // native_typeface is passed here since Framework's old implementation did not have the
-        // typeface object associated with the Paint. Since, we follow the new framework way,
-        // we store the typeface with the paint and use it directly.
-        assert (native_typeface == delegate.mNativeTypeface);
-
-        RectF bounds = delegate.measureText(text, index, count, widths, 0, bidiFlags);
-        return ((int) (bounds.right - bounds.left));
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static int native_getTextWidths(long native_object, long native_typeface,
-            String text, int start, int end, int bidiFlags, float[] widths) {
-        return native_getTextWidths(native_object, native_typeface, text.toCharArray(), start,
-                end - start, bidiFlags, widths);
-    }
-
-    @LayoutlibDelegate
-    /* package */static int native_getTextGlyphs(long native_object, String text, int start,
-            int end, int contextStart, int contextEnd, int flags, char[] glyphs) {
-        // FIXME
+        delegate.setTextLocale(locale);
         return 0;
     }
 
     @LayoutlibDelegate
-    /*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface,
+    /*package*/ static void nSetTextLocalesByMinikinLangListId(long paintPtr,
+            int mMinikinLangListId) {
+        // FIXME
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
             char[] text, int index, int count, int contextIndex, int contextCount,
-            boolean isRtl, float[] advances, int advancesIndex) {
+            int bidiFlags, float[] advances, int advancesIndex) {
 
         if (advances != null)
             for (int i = advancesIndex; i< advancesIndex+count; i++)
@@ -1017,25 +972,25 @@
         // we store the typeface with the paint and use it directly.
         assert (native_typeface == delegate.mNativeTypeface);
 
-        RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, isRtl);
+        RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, bidiFlags);
         return bounds.right - bounds.left;
     }
 
     @LayoutlibDelegate
-    /*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface,
+    /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
             String text, int start, int end, int contextStart, int contextEnd,
-            boolean isRtl, float[] advances, int advancesIndex) {
+            int bidiFlags, float[] advances, int advancesIndex) {
         // FIXME: support contextStart and contextEnd
         int count = end - start;
         char[] buffer = TemporaryBuffer.obtain(count);
         TextUtils.getChars(text, start, end, buffer, 0);
 
-        return native_getTextRunAdvances(native_object, native_typeface, buffer, 0, count,
-                contextStart, contextEnd - contextStart, isRtl, advances, advancesIndex);
+        return nGetTextAdvances(native_object, native_typeface, buffer, 0, count,
+                contextStart, contextEnd - contextStart, bidiFlags, advances, advancesIndex);
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, char[] text,
+    /*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, char[] text,
             int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1044,7 +999,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, String text,
+    /*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, String text,
             int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1053,7 +1008,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_getTextPath(long native_object, long native_typeface,
+    /*package*/ static void nGetTextPath(long native_object, long native_typeface,
             int bidiFlags, char[] text, int index, int count, float x, float y, long path) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1061,7 +1016,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_getTextPath(long native_object, long native_typeface,
+    /*package*/ static void nGetTextPath(long native_object, long native_typeface,
             int bidiFlags, String text, int start, int end, float x, float y, long path) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1069,14 +1024,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeGetStringBounds(long nativePaint, long native_typeface,
+    /*package*/ static void nGetStringBounds(long nativePaint, long native_typeface,
             String text, int start, int end, int bidiFlags, Rect bounds) {
-        nativeGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
+        nGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
                 end - start, bidiFlags, bounds);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeGetCharArrayBounds(long nativePaint, long native_typeface,
+    /*package*/ static void nGetCharArrayBounds(long nativePaint, long native_typeface,
             char[] text, int index, int count, int bidiFlags, Rect bounds) {
 
         // get the delegate from the native int.
@@ -1092,12 +1047,18 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void finalizer(long nativePaint) {
-        sManager.removeJavaReferenceFor(nativePaint);
+    /*package*/ static long nGetNativeFinalizer() {
+        synchronized (Paint_Delegate.class) {
+            if (sFinalizer == -1) {
+                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(
+                        sManager::removeJavaReferenceFor);
+            }
+        }
+        return sFinalizer;
     }
 
     @LayoutlibDelegate
-    /*package*/ static float native_getLetterSpacing(long nativePaint) {
+    /*package*/ static float nGetLetterSpacing(long nativePaint) {
         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
@@ -1106,7 +1067,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setLetterSpacing(long nativePaint, float letterSpacing) {
+    /*package*/ static void nSetLetterSpacing(long nativePaint, float letterSpacing) {
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
                 "Paint.setLetterSpacing() not supported.", null, null);
         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
@@ -1117,13 +1078,13 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setFontFeatureSettings(long nativePaint, String settings) {
+    /*package*/ static void nSetFontFeatureSettings(long nativePaint, String settings) {
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
                 "Paint.setFontFeatureSettings() not supported.", null, null);
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getHyphenEdit(long nativePaint) {
+    /*package*/ static int nGetHyphenEdit(long nativePaint) {
         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return 0;
@@ -1132,7 +1093,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setHyphenEdit(long nativePaint, int hyphen) {
+    /*package*/ static void nSetHyphenEdit(long nativePaint, int hyphen) {
         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
@@ -1141,7 +1102,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_hasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
+    /*package*/ static boolean nHasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
             String string) {
         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
@@ -1169,13 +1130,14 @@
 
 
     @LayoutlibDelegate
-    /*package*/ static float native_getRunAdvance(long nativePaint, long nativeTypeface,
+    /*package*/ static float nGetRunAdvance(long nativePaint, long nativeTypeface,
             @NonNull char[] text, int start, int end, int contextStart, int contextEnd,
             boolean isRtl, int offset) {
         int count = end - start;
         float[] advances = new float[count];
-        native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count,
-                contextStart, contextEnd - contextStart, isRtl, advances, 0);
+        int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
+        nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
+                contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
         int startOffset = offset - start;  // offset from start.
         float sum = 0;
         for (int i = 0; i < startOffset; i++) {
@@ -1185,13 +1147,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getOffsetForAdvance(long nativePaint, long nativeTypeface,
+    /*package*/ static int nGetOffsetForAdvance(long nativePaint, long nativeTypeface,
             char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl,
             float advance) {
         int count = end - start;
         float[] advances = new float[count];
-        native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count,
-                contextStart, contextEnd - contextStart, isRtl, advances, 0);
+        int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
+        nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
+                contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
         float sum = 0;
         int i;
         for (i = 0; i < count && sum < advance; i++) {
@@ -1359,9 +1322,9 @@
         mLocale = new Locale(locale);
     }
 
-    private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
+    private static void setFlag(long nativePaint, int flagMask, boolean flagValue) {
         // get the delegate from the native int.
-        Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+        Paint_Delegate delegate = sManager.getDelegate(nativePaint);
         if (delegate == null) {
             return;
         }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index a10ac00..e1da27b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -75,7 +75,7 @@
         return sManager.getDelegate(nPath);
     }
 
-    public Shape getJavaShape() {
+    public Path2D getJavaShape() {
         return mPath;
     }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 85e65e6..5cd34f6 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -24,8 +24,10 @@
 
 import java.awt.Font;
 import java.io.File;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import static android.graphics.FontFamily_Delegate.getFontLocation;
 
@@ -205,6 +207,17 @@
         return new File(getFontLocation());
     }
 
+    @LayoutlibDelegate
+    /*package*/ static FontFamily makeFamilyFromParsed(FontListParser.Family family,
+            Map<String, ByteBuffer> bufferForPath) {
+        FontFamily fontFamily = new FontFamily(family.lang, family.variant);
+        for (FontListParser.Font font : family.fonts) {
+            FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.fontName, font.weight,
+                    font.isItalic);
+        }
+        return fontFamily;
+    }
+
     // ---- Private delegate/helper methods ----
 
     private Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style) {
diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
index 44ce731..fcd63ea 100644
--- a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
@@ -25,7 +25,7 @@
 /**
  * Delegate that overrides implementation for certain methods in {@link android.text.Hyphenator}
  * <p/>
- * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
+ * Through the layoutlib_create tool, selected methods of Hyphenator have been replaced
  * by calls to methods of the same name in this delegate class.
  */
 public class Hyphenator_Delegate {
@@ -39,7 +39,8 @@
         return null;
     }
 
-    /*package*/ static long loadHyphenator(ByteBuffer buf, int offset) {
+    /*package*/ @SuppressWarnings("UnusedParameters")  // TODO implement this.
+    static long loadHyphenator(ByteBuffer buffer, int offset) {
         return sDelegateManager.addNewDelegate(new Hyphenator_Delegate());
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
new file mode 100644
index 0000000..d3af837
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
@@ -0,0 +1,757 @@
+/*
+ * Copyright (C) 2015 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.util;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.annotation.NonNull;
+import android.graphics.Path_Delegate;
+
+import java.awt.geom.Path2D;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Delegate that provides implementation for native methods in {@link android.util.PathParser}
+ * <p/>
+ * Through the layoutlib_create tool, selected methods of PathParser have been replaced by calls to
+ * methods of the same name in this delegate class.
+ *
+ * Most of the code has been taken from the implementation in
+ * {@code tools/base/sdk-common/src/main/java/com/android/ide/common/vectordrawable/PathParser.java}
+ * revision be6fe89a3b686db5a75e7e692a148699973957f3
+ */
+public class PathParser_Delegate {
+
+    private static final Logger LOGGER = Logger.getLogger("PathParser");
+
+    // ---- Builder delegate manager ----
+    private static final DelegateManager<PathParser_Delegate> sManager =
+            new DelegateManager<PathParser_Delegate>(PathParser_Delegate.class);
+
+    // ---- delegate data ----
+    @NonNull
+    private PathDataNode[] mPathDataNodes;
+
+    private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
+        mPathDataNodes = nodes;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
+            stringLength) {
+        Path_Delegate path_delegate = Path_Delegate.getDelegate(pathPtr);
+        if (path_delegate == null) {
+            return false;
+        }
+        assert pathString.length() == stringLength;
+        PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate.getJavaShape());
+        return true;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nCreatePathFromPathData(long outPathPtr, long pathData) {
+        Path_Delegate path_delegate = Path_Delegate.getDelegate(outPathPtr);
+        PathParser_Delegate source = sManager.getDelegate(outPathPtr);
+        if (source == null || path_delegate == null) {
+            return;
+        }
+        PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate.getJavaShape());
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreateEmptyPathData() {
+        PathParser_Delegate newDelegate = new PathParser_Delegate(new PathDataNode[0]);
+        return sManager.addNewDelegate(newDelegate);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathData(long nativePtr) {
+        PathParser_Delegate source = sManager.getDelegate(nativePtr);
+        if (source == null) {
+            return 0;
+        }
+        PathParser_Delegate dest = new PathParser_Delegate(deepCopyNodes(source.mPathDataNodes));
+        return sManager.addNewDelegate(dest);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static long nCreatePathDataFromString(@NonNull String pathString,
+            int stringLength) {
+        assert pathString.length() == stringLength : "Inconsistent path string length.";
+        PathDataNode[] nodes = createNodesFromPathData(pathString);
+        PathParser_Delegate delegate = new PathParser_Delegate(nodes);
+        return sManager.addNewDelegate(delegate);
+
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static boolean nInterpolatePathData(long outDataPtr, long fromDataPtr,
+            long toDataPtr, float fraction) {
+        PathParser_Delegate out = sManager.getDelegate(outDataPtr);
+        PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
+        PathParser_Delegate to = sManager.getDelegate(toDataPtr);
+        if (out == null || from == null || to == null) {
+            return false;
+        }
+        int length = from.mPathDataNodes.length;
+        if (length != to.mPathDataNodes.length) {
+            Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                    "Cannot interpolate path data with different lengths (from " + length + " to " +
+                            to.mPathDataNodes.length + ").", null);
+            return false;
+        }
+        if (out.mPathDataNodes.length != length) {
+            out.mPathDataNodes = new PathDataNode[length];
+        }
+        for (int i = 0; i < length; i++) {
+            out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
+                    to.mPathDataNodes[i], fraction);
+        }
+        return true;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nFinalize(long nativePtr) {
+        sManager.removeJavaReferenceFor(nativePtr);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "morphing path data isn't " +
+                "supported", null, null);
+        return false;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nSetPathData(long outDataPtr, long fromDataPtr) {
+        PathParser_Delegate out = sManager.getDelegate(outDataPtr);
+        PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
+        if (from == null || out == null) {
+            return;
+        }
+        out.mPathDataNodes = deepCopyNodes(from.mPathDataNodes);
+    }
+
+    /**
+     * @param pathData The string representing a path, the same as "d" string in svg file.
+     *
+     * @return an array of the PathDataNode.
+     */
+    @NonNull
+    private static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
+        int start = 0;
+        int end = 1;
+
+        ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
+        while (end < pathData.length()) {
+            end = nextStart(pathData, end);
+            String s = pathData.substring(start, end).trim();
+            if (s.length() > 0) {
+                float[] val = getFloats(s);
+                addNode(list, s.charAt(0), val);
+            }
+
+            start = end;
+            end++;
+        }
+        if ((end - start) == 1 && start < pathData.length()) {
+            addNode(list, pathData.charAt(start), new float[0]);
+        }
+        return list.toArray(new PathDataNode[list.size()]);
+    }
+
+    /**
+     * @param source The array of PathDataNode to be duplicated.
+     *
+     * @return a deep copy of the <code>source</code>.
+     */
+    @NonNull
+    private static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
+        PathDataNode[] copy = new PathDataNode[source.length];
+        for (int i = 0; i < source.length; i++) {
+            copy[i] = new PathDataNode(source[i]);
+        }
+        return copy;
+    }
+
+    private static int nextStart(@NonNull String s, int end) {
+        char c;
+
+        while (end < s.length()) {
+            c = s.charAt(end);
+            // Note that 'e' or 'E' are not valid path commands, but could be
+            // used for floating point numbers' scientific notation.
+            // Therefore, when searching for next command, we should ignore 'e'
+            // and 'E'.
+            if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
+                    && c != 'e' && c != 'E') {
+                return end;
+            }
+            end++;
+        }
+        return end;
+    }
+
+    /**
+     * Calculate the position of the next comma or space or negative sign
+     *
+     * @param s the string to search
+     * @param start the position to start searching
+     * @param result the result of the extraction, including the position of the the starting
+     * position of next number, whether it is ending with a '-'.
+     */
+    private static void extract(@NonNull String s, int start, @NonNull ExtractFloatResult result) {
+        // Now looking for ' ', ',', '.' or '-' from the start.
+        int currentIndex = start;
+        boolean foundSeparator = false;
+        result.mEndWithNegOrDot = false;
+        boolean secondDot = false;
+        boolean isExponential = false;
+        for (; currentIndex < s.length(); currentIndex++) {
+            boolean isPrevExponential = isExponential;
+            isExponential = false;
+            char currentChar = s.charAt(currentIndex);
+            switch (currentChar) {
+                case ' ':
+                case ',':
+                    foundSeparator = true;
+                    break;
+                case '-':
+                    // The negative sign following a 'e' or 'E' is not a separator.
+                    if (currentIndex != start && !isPrevExponential) {
+                        foundSeparator = true;
+                        result.mEndWithNegOrDot = true;
+                    }
+                    break;
+                case '.':
+                    if (!secondDot) {
+                        secondDot = true;
+                    } else {
+                        // This is the second dot, and it is considered as a separator.
+                        foundSeparator = true;
+                        result.mEndWithNegOrDot = true;
+                    }
+                    break;
+                case 'e':
+                case 'E':
+                    isExponential = true;
+                    break;
+            }
+            if (foundSeparator) {
+                break;
+            }
+        }
+        // When there is nothing found, then we put the end position to the end
+        // of the string.
+        result.mEndPosition = currentIndex;
+    }
+
+    /**
+     * Parse the floats in the string. This is an optimized version of
+     * parseFloat(s.split(",|\\s"));
+     *
+     * @param s the string containing a command and list of floats
+     *
+     * @return array of floats
+     */
+    @NonNull
+    private static float[] getFloats(@NonNull String s) {
+        if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') {
+            return new float[0];
+        }
+        try {
+            float[] results = new float[s.length()];
+            int count = 0;
+            int startPosition = 1;
+            int endPosition;
+
+            ExtractFloatResult result = new ExtractFloatResult();
+            int totalLength = s.length();
+
+            // The startPosition should always be the first character of the
+            // current number, and endPosition is the character after the current
+            // number.
+            while (startPosition < totalLength) {
+                extract(s, startPosition, result);
+                endPosition = result.mEndPosition;
+
+                if (startPosition < endPosition) {
+                    results[count++] = Float.parseFloat(
+                            s.substring(startPosition, endPosition));
+                }
+
+                if (result.mEndWithNegOrDot) {
+                    // Keep the '-' or '.' sign with next number.
+                    startPosition = endPosition;
+                } else {
+                    startPosition = endPosition + 1;
+                }
+            }
+            return Arrays.copyOf(results, count);
+        } catch (NumberFormatException e) {
+            throw new RuntimeException("error in parsing \"" + s + "\"", e);
+        }
+    }
+
+
+    private static void addNode(@NonNull ArrayList<PathDataNode> list, char cmd,
+            @NonNull float[] val) {
+        list.add(new PathDataNode(cmd, val));
+    }
+
+    private static class ExtractFloatResult {
+        // We need to return the position of the next separator and whether the
+        // next float starts with a '-' or a '.'.
+        private int mEndPosition;
+        private boolean mEndWithNegOrDot;
+    }
+
+    /**
+     * Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
+     * PathDataNode can represent the whole "d" attribute.
+     */
+    private static class PathDataNode {
+        private char mType;
+        @NonNull
+        private float[] mParams;
+
+        private PathDataNode(char type, @NonNull float[] params) {
+            mType = type;
+            mParams = params;
+        }
+
+        public char getType() {
+            return mType;
+        }
+
+        @NonNull
+        public float[] getParams() {
+            return mParams;
+        }
+
+        private PathDataNode(@NonNull PathDataNode n) {
+            mType = n.mType;
+            mParams = Arrays.copyOf(n.mParams, n.mParams.length);
+        }
+
+        /**
+         * Convert an array of PathDataNode to Path.
+         *
+         * @param node The source array of PathDataNode.
+         * @param path The target Path object.
+         */
+        private static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path2D path) {
+            float[] current = new float[6];
+            char previousCommand = 'm';
+            //noinspection ForLoopReplaceableByForEach
+            for (int i = 0; i < node.length; i++) {
+                addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
+                previousCommand = node[i].mType;
+            }
+        }
+
+        /**
+         * The current PathDataNode will be interpolated between the <code>nodeFrom</code> and
+         * <code>nodeTo</code> according to the <code>fraction</code>.
+         *
+         * @param nodeFrom The start value as a PathDataNode.
+         * @param nodeTo The end value as a PathDataNode
+         * @param fraction The fraction to interpolate.
+         */
+        private void interpolatePathDataNode(@NonNull PathDataNode nodeFrom,
+                @NonNull PathDataNode nodeTo, float fraction) {
+            for (int i = 0; i < nodeFrom.mParams.length; i++) {
+                mParams[i] = nodeFrom.mParams[i] * (1 - fraction)
+                        + nodeTo.mParams[i] * fraction;
+            }
+        }
+
+        @SuppressWarnings("PointlessArithmeticExpression")
+        private static void addCommand(@NonNull Path2D path, float[] current, char cmd,
+                char lastCmd, @NonNull float[] val) {
+
+            int incr = 2;
+
+            float cx = current[0];
+            float cy = current[1];
+            float cpx = current[2];
+            float cpy = current[3];
+            float loopX = current[4];
+            float loopY = current[5];
+
+            switch (cmd) {
+                case 'z':
+                case 'Z':
+                    path.closePath();
+                    cx = loopX;
+                    cy = loopY;
+                case 'm':
+                case 'M':
+                case 'l':
+                case 'L':
+                case 't':
+                case 'T':
+                    incr = 2;
+                    break;
+                case 'h':
+                case 'H':
+                case 'v':
+                case 'V':
+                    incr = 1;
+                    break;
+                case 'c':
+                case 'C':
+                    incr = 6;
+                    break;
+                case 's':
+                case 'S':
+                case 'q':
+                case 'Q':
+                    incr = 4;
+                    break;
+                case 'a':
+                case 'A':
+                    incr = 7;
+            }
+
+            for (int k = 0; k < val.length; k += incr) {
+                boolean reflectCtrl;
+                float tempReflectedX, tempReflectedY;
+
+                switch (cmd) {
+                    case 'm':
+                        cx += val[k + 0];
+                        cy += val[k + 1];
+                        if (k > 0) {
+                            // According to the spec, if a moveto is followed by multiple
+                            // pairs of coordinates, the subsequent pairs are treated as
+                            // implicit lineto commands.
+                            path.lineTo(cx, cy);
+                        } else {
+                            path.moveTo(cx, cy);
+                            loopX = cx;
+                            loopY = cy;
+                        }
+                        break;
+                    case 'M':
+                        cx = val[k + 0];
+                        cy = val[k + 1];
+                        if (k > 0) {
+                            // According to the spec, if a moveto is followed by multiple
+                            // pairs of coordinates, the subsequent pairs are treated as
+                            // implicit lineto commands.
+                            path.lineTo(cx, cy);
+                        } else {
+                            path.moveTo(cx, cy);
+                            loopX = cx;
+                            loopY = cy;
+                        }
+                        break;
+                    case 'l':
+                        cx += val[k + 0];
+                        cy += val[k + 1];
+                        path.lineTo(cx, cy);
+                        break;
+                    case 'L':
+                        cx = val[k + 0];
+                        cy = val[k + 1];
+                        path.lineTo(cx, cy);
+                        break;
+                    case 'z':
+                    case 'Z':
+                        path.closePath();
+                        cx = loopX;
+                        cy = loopY;
+                        break;
+                    case 'h':
+                        cx += val[k + 0];
+                        path.lineTo(cx, cy);
+                        break;
+                    case 'H':
+                        path.lineTo(val[k + 0], cy);
+                        cx = val[k + 0];
+                        break;
+                    case 'v':
+                        cy += val[k + 0];
+                        path.lineTo(cx, cy);
+                        break;
+                    case 'V':
+                        path.lineTo(cx, val[k + 0]);
+                        cy = val[k + 0];
+                        break;
+                    case 'c':
+                        path.curveTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
+                                cy + val[k + 3], cx + val[k + 4], cy + val[k + 5]);
+                        cpx = cx + val[k + 2];
+                        cpy = cy + val[k + 3];
+                        cx += val[k + 4];
+                        cy += val[k + 5];
+                        break;
+                    case 'C':
+                        path.curveTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                                val[k + 4], val[k + 5]);
+                        cx = val[k + 4];
+                        cy = val[k + 5];
+                        cpx = val[k + 2];
+                        cpy = val[k + 3];
+                        break;
+                    case 's':
+                        reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
+                                lastCmd == 'S');
+                        path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
+                                * cy - cpy : cy, cx + val[k + 0], cy + val[k + 1], cx
+                                + val[k + 2], cy + val[k + 3]);
+
+                        cpx = cx + val[k + 0];
+                        cpy = cy + val[k + 1];
+                        cx += val[k + 2];
+                        cy += val[k + 3];
+                        break;
+                    case 'S':
+                        reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
+                                lastCmd == 'S');
+                        path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
+                                        * cy - cpy : cy, val[k + 0], val[k + 1], val[k + 2],
+                                val[k + 3]);
+                        cpx = (val[k + 0]);
+                        cpy = (val[k + 1]);
+                        cx = val[k + 2];
+                        cy = val[k + 3];
+                        break;
+                    case 'q':
+                        path.quadTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
+                                cy + val[k + 3]);
+                        cpx = cx + val[k + 0];
+                        cpy = cy + val[k + 1];
+                        // Note that we have to update cpx first, since cx will be updated here.
+                        cx += val[k + 2];
+                        cy += val[k + 3];
+                        break;
+                    case 'Q':
+                        path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        cx = val[k + 2];
+                        cy = val[k + 3];
+                        cpx = val[k + 0];
+                        cpy = val[k + 1];
+                        break;
+                    case 't':
+                        reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
+                                lastCmd == 'T');
+                        tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
+                        tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
+                        path.quadTo(tempReflectedX, tempReflectedY, cx + val[k + 0],
+                                cy + val[k + 1]);
+                        cpx = tempReflectedX;
+                        cpy = tempReflectedY;
+                        cx += val[k + 0];
+                        cy += val[k + 1];
+                        break;
+                    case 'T':
+                        reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
+                                lastCmd == 'T');
+                        tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
+                        tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
+                        path.quadTo(tempReflectedX, tempReflectedY, val[k + 0], val[k + 1]);
+                        cx = val[k + 0];
+                        cy = val[k + 1];
+                        cpx = tempReflectedX;
+                        cpy = tempReflectedY;
+                        break;
+                    case 'a':
+                        // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+                        drawArc(path, cx, cy, val[k + 5] + cx, val[k + 6] + cy,
+                                val[k + 0], val[k + 1], val[k + 2], val[k + 3] != 0,
+                                val[k + 4] != 0);
+                        cx += val[k + 5];
+                        cy += val[k + 6];
+                        cpx = cx;
+                        cpy = cy;
+
+                        break;
+                    case 'A':
+                        drawArc(path, cx, cy, val[k + 5], val[k + 6], val[k + 0],
+                                val[k + 1], val[k + 2], val[k + 3] != 0,
+                                val[k + 4] != 0);
+                        cx = val[k + 5];
+                        cy = val[k + 6];
+                        cpx = cx;
+                        cpy = cy;
+                        break;
+
+                }
+                lastCmd = cmd;
+            }
+            current[0] = cx;
+            current[1] = cy;
+            current[2] = cpx;
+            current[3] = cpy;
+            current[4] = loopX;
+            current[5] = loopY;
+
+        }
+
+        private static void drawArc(@NonNull Path2D p, float x0, float y0, float x1,
+                float y1, float a, float b, float theta, boolean isMoreThanHalf,
+                boolean isPositiveArc) {
+
+            LOGGER.log(Level.FINE, "(" + x0 + "," + y0 + ")-(" + x1 + "," + y1
+                    + ") {" + a + " " + b + "}");
+        /* Convert rotation angle from degrees to radians */
+            double thetaD = theta * Math.PI / 180.0f;
+        /* Pre-compute rotation matrix entries */
+            double cosTheta = Math.cos(thetaD);
+            double sinTheta = Math.sin(thetaD);
+        /* Transform (x0, y0) and (x1, y1) into unit space */
+        /* using (inverse) rotation, followed by (inverse) scale */
+            double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
+            double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
+            double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
+            double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
+            LOGGER.log(Level.FINE, "unit space (" + x0p + "," + y0p + ")-(" + x1p
+                    + "," + y1p + ")");
+        /* Compute differences and averages */
+            double dx = x0p - x1p;
+            double dy = y0p - y1p;
+            double xm = (x0p + x1p) / 2;
+            double ym = (y0p + y1p) / 2;
+        /* Solve for intersecting unit circles */
+            double dsq = dx * dx + dy * dy;
+            if (dsq == 0.0) {
+                LOGGER.log(Level.FINE, " Points are coincident");
+                return; /* Points are coincident */
+            }
+            double disc = 1.0 / dsq - 1.0 / 4.0;
+            if (disc < 0.0) {
+                LOGGER.log(Level.FINE, "Points are too far apart " + dsq);
+                float adjust = (float) (Math.sqrt(dsq) / 1.99999);
+                drawArc(p, x0, y0, x1, y1, a * adjust, b * adjust, theta,
+                        isMoreThanHalf, isPositiveArc);
+                return; /* Points are too far apart */
+            }
+            double s = Math.sqrt(disc);
+            double sdx = s * dx;
+            double sdy = s * dy;
+            double cx;
+            double cy;
+            if (isMoreThanHalf == isPositiveArc) {
+                cx = xm - sdy;
+                cy = ym + sdx;
+            } else {
+                cx = xm + sdy;
+                cy = ym - sdx;
+            }
+
+            double eta0 = Math.atan2((y0p - cy), (x0p - cx));
+            LOGGER.log(Level.FINE, "eta0 = Math.atan2( " + (y0p - cy) + " , "
+                    + (x0p - cx) + ") = " + Math.toDegrees(eta0));
+
+            double eta1 = Math.atan2((y1p - cy), (x1p - cx));
+            LOGGER.log(Level.FINE, "eta1 = Math.atan2( " + (y1p - cy) + " , "
+                    + (x1p - cx) + ") = " + Math.toDegrees(eta1));
+            double sweep = (eta1 - eta0);
+            if (isPositiveArc != (sweep >= 0)) {
+                if (sweep > 0) {
+                    sweep -= 2 * Math.PI;
+                } else {
+                    sweep += 2 * Math.PI;
+                }
+            }
+
+            cx *= a;
+            cy *= b;
+            double tcx = cx;
+            cx = cx * cosTheta - cy * sinTheta;
+            cy = tcx * sinTheta + cy * cosTheta;
+            LOGGER.log(
+                    Level.FINE,
+                    "cx, cy, a, b, x0, y0, thetaD, eta0, sweep = " + cx + " , "
+                            + cy + " , " + a + " , " + b + " , " + x0 + " , " + y0
+                            + " , " + Math.toDegrees(thetaD) + " , "
+                            + Math.toDegrees(eta0) + " , " + Math.toDegrees(sweep));
+
+            arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
+        }
+
+        /**
+         * Converts an arc to cubic Bezier segments and records them in p.
+         *
+         * @param p The target for the cubic Bezier segments
+         * @param cx The x coordinate center of the ellipse
+         * @param cy The y coordinate center of the ellipse
+         * @param a The radius of the ellipse in the horizontal direction
+         * @param b The radius of the ellipse in the vertical direction
+         * @param e1x E(eta1) x coordinate of the starting point of the arc
+         * @param e1y E(eta2) y coordinate of the starting point of the arc
+         * @param theta The angle that the ellipse bounding rectangle makes with the horizontal
+         * plane
+         * @param start The start angle of the arc on the ellipse
+         * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
+         */
+        private static void arcToBezier(@NonNull Path2D p, double cx, double cy, double a,
+                double b, double e1x, double e1y, double theta, double start,
+                double sweep) {
+            // Taken from equations at:
+            // http://spaceroots.org/documents/ellipse/node8.html
+            // and http://www.spaceroots.org/documents/ellipse/node22.html
+            // Maximum of 45 degrees per cubic Bezier segment
+            int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI));
+
+
+            double eta1 = start;
+            double cosTheta = Math.cos(theta);
+            double sinTheta = Math.sin(theta);
+            double cosEta1 = Math.cos(eta1);
+            double sinEta1 = Math.sin(eta1);
+            double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
+            double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
+
+            double anglePerSegment = sweep / numSegments;
+            for (int i = 0; i < numSegments; i++) {
+                double eta2 = eta1 + anglePerSegment;
+                double sinEta2 = Math.sin(eta2);
+                double cosEta2 = Math.cos(eta2);
+                double e2x = cx + (a * cosTheta * cosEta2)
+                        - (b * sinTheta * sinEta2);
+                double e2y = cy + (a * sinTheta * cosEta2)
+                        + (b * cosTheta * sinEta2);
+                double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
+                double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
+                double tanDiff2 = Math.tan((eta2 - eta1) / 2);
+                double alpha = Math.sin(eta2 - eta1)
+                        * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
+                double q1x = e1x + alpha * ep1x;
+                double q1y = e1y + alpha * ep1y;
+                double q2x = e2x - alpha * ep2x;
+                double q2y = e2y - alpha * ep2y;
+
+                p.curveTo((float) q1x, (float) q1y, (float) q2x, (float) q2y,
+                        (float) e2x, (float) e2y);
+                eta1 = eta2;
+                e1x = e2x;
+                e1y = e2y;
+                ep1x = ep2x;
+                ep1y = ep2y;
+            }
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java b/tools/layoutlib/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java
deleted file mode 100644
index 1bd9830..0000000
--- a/tools/layoutlib/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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 android.widget;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.view.KeyEvent;
-
-/**
- * Delegate used to provide new implementation of few methods in {@link TimePickerClockDelegate}.
- */
-public class TimePickerClockDelegate_Delegate {
-
-    // Copied from TimePickerClockDelegate.
-    private static final int AM = 0;
-    private static final int PM = 1;
-
-    @LayoutlibDelegate
-    static int getAmOrPmKeyCode(TimePickerClockDelegate tpcd, int amOrPm) {
-        // We don't care about locales here.
-        if (amOrPm == AM) {
-            return KeyEvent.KEYCODE_A;
-        } else if (amOrPm == PM) {
-            return KeyEvent.KEYCODE_P;
-        } else {
-            assert false : "amOrPm value in TimePickerSpinnerDelegate can only be 0 or 1";
-            return -1;
-        }
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
index 8c60bae..c0ca1d5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
@@ -36,9 +36,9 @@
 /**
  * A Helper class to do fake data binding in {@link AdapterView} objects.
  */
-@SuppressWarnings("deprecation")
 public class AdapterHelper {
 
+    @SuppressWarnings("deprecation")
     static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
             LayoutlibCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
         // we don't care about recycling here because we never scroll.
diff --git a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java
new file mode 100644
index 0000000..6246ec1b8
--- /dev/null
+++ b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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 libcore.util;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate implementing the native methods of {@link NativeAllocationRegistry}
+ *
+ * Through the layoutlib_create tool, the original native methods of NativeAllocationRegistry have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original NativeAllocationRegistry class.
+ *
+ * @see DelegateManager
+ */
+public class NativeAllocationRegistry_Delegate {
+
+    // ---- delegate manager ----
+    private static final DelegateManager<NativeAllocationRegistry_Delegate> sManager =
+            new DelegateManager<>(NativeAllocationRegistry_Delegate.class);
+
+    private final FreeFunction mFinalizer;
+
+    private NativeAllocationRegistry_Delegate(FreeFunction finalizer) {
+        mFinalizer = finalizer;
+    }
+
+    /**
+     * The result of this method should be cached by the class and reused.
+     */
+    public static long createFinalizer(FreeFunction finalizer) {
+        return sManager.addNewDelegate(new NativeAllocationRegistry_Delegate(finalizer));
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) {
+        NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction);
+        if (delegate != null) {
+            delegate.mFinalizer.free(nativePtr);
+        }
+    }
+
+    public interface FreeFunction {
+        void free(long nativePtr);
+    }
+}
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index 5eef24a..8a81d0b 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -19,7 +19,6 @@
 # Only compile source java files in this lib.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_JAVA_RESOURCE_DIRS := res
-LOCAL_JAVACFLAGS := -source 6 -target 6
 
 LOCAL_MODULE := layoutlib-tests
 LOCAL_MODULE_TAGS := optional
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
index 16911bd..8f9fa8a2 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
@@ -75,8 +75,12 @@
             }
         }
         else {
-            BufferedImage goldenImage = ImageIO.read(is);
-            assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE);
+            try {
+                BufferedImage goldenImage = ImageIO.read(is);
+                assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE);
+            } finally {
+                is.close();
+            }
         }
     }
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
index 758bd48..01c940a 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
@@ -176,17 +176,6 @@
             }
         }
 
-        /* Java 7 verifies the StackMapTable of a class if its version number is greater than 50.0.
-         * However, the check is disabled if the class version number is 50.0 or less. Generation
-         * of the StackMapTable requires a rewrite using the tree API of ASM. As a workaround,
-         * we rewrite the version number of the class to be 50.0
-         *
-         * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6693236
-         */
-        if (version > 50) {
-            version = 50;
-        }
-
         super.visit(version, access, name, signature, superName, interfaces);
     }
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index d106592..189ecdc 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -144,11 +144,8 @@
             InjectMethodRunnable.class,
             InjectMethodRunnables.class,
             /* Java package classes */
-            AutoCloseable.class,
-            Objects.class,
             IntegralToString.class,
             UnsafeByteSequence.class,
-            Charsets.class,
             System_Delegate.class,
             LinkedHashMap_Delegate.class,
         };
@@ -169,6 +166,7 @@
         "android.graphics.BitmapFactory#setDensityFromOptions",
         "android.graphics.drawable.GradientDrawable#buildRing",
         "android.graphics.Typeface#getSystemFontConfigLocation",
+        "android.graphics.Typeface#makeFamilyFromParsed",
         "android.os.Handler#sendMessageAtTime",
         "android.os.HandlerThread#run",
         "android.preference.Preference#getView",
@@ -188,6 +186,7 @@
         "android.view.WindowManagerGlobal#getWindowManagerService",
         "android.view.inputmethod.InputMethodManager#getInstance",
         "android.view.MenuInflater#registerMenu",
+        "android.view.RenderNode#getMatrix",
         "android.view.RenderNode#nCreate",
         "android.view.RenderNode#nDestroyRenderNode",
         "android.view.RenderNode#nSetElevation",
@@ -200,7 +199,6 @@
         "android.view.RenderNode#nGetTranslationZ",
         "android.view.RenderNode#nSetRotation",
         "android.view.RenderNode#nGetRotation",
-        "android.view.RenderNode#getMatrix",
         "android.view.RenderNode#nSetLeft",
         "android.view.RenderNode#nSetTop",
         "android.view.RenderNode#nSetRight",
@@ -216,7 +214,6 @@
         "android.view.RenderNode#nGetScaleY",
         "android.view.RenderNode#nIsPivotExplicitlySet",
         "android.view.ViewGroup#drawChild",
-        "android.widget.TimePickerClockDelegate#getAmOrPmKeyCode",
         "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
         "com.android.internal.util.XmlUtils#convertValueToInt",
         "com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
@@ -224,6 +221,7 @@
         "libcore.io.MemoryMappedFile#mmapRO",
         "libcore.io.MemoryMappedFile#close",
         "libcore.io.MemoryMappedFile#bigEndianIterator",
+        "libcore.util.NativeAllocationRegistry#applyFreeFunction",
     };
 
     /**
@@ -274,6 +272,7 @@
         "android.os.SystemProperties",
         "android.text.AndroidBidi",
         "android.text.StaticLayout",
+        "android.util.PathParser",
         "android.view.Display",
         "libcore.icu.ICU",
     };
@@ -306,12 +305,9 @@
      */
     private final static String[] JAVA_PKG_CLASSES =
         new String[] {
-            "java.lang.AutoCloseable",                         "com.android.tools.layoutlib.java.AutoCloseable",
-            "java.util.Objects",                               "com.android.tools.layoutlib.java.Objects",
-            "java.nio.charset.Charsets",                       "com.android.tools.layoutlib.java.Charsets",
+            "java.nio.charset.Charsets",                       "java.nio.charset.StandardCharsets",
             "java.lang.IntegralToString",                      "com.android.tools.layoutlib.java.IntegralToString",
             "java.lang.UnsafeByteSequence",                    "com.android.tools.layoutlib.java.UnsafeByteSequence",
-            "java.nio.charset.StandardCharsets",               "com.android.tools.layoutlib.java.Charsets",
         };
 
     private final static String[] EXCLUDED_CLASSES =
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
index b5ab738..4ba7237 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
@@ -103,6 +103,7 @@
                 mParentVisitor.visitInsn(Opcodes.ICONST_1);
                 mParentVisitor.visitInsn(Opcodes.IRETURN);
                 mParentVisitor.visitLabel(l1);
+                mParentVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                 mParentVisitor.visitInsn(Opcodes.ICONST_0);
                 break;
             case Type.CHAR: